//package com.xdtech.core.annotation;
//
///*
// * Hibernate, Relational Persistence for Idiomatic Java
// *
// * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
// * indicated by the @author tags or express copyright attribution
// * statements applied by the authors.  All third-party contributions are
// * distributed under license by Red Hat Inc.
// *
// * This copyrighted material is made available to anyone wishing to use, modify,
// * copy, or redistribute it subject to the terms and conditions of the GNU
// * Lesser General Public License, as published by the Free Software Foundation.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
// * for more details.
// *
// * You should have received a copy of the GNU Lesser General Public License
// * along with this distribution; if not, write to:
// * Free Software Foundation, Inc.
// * 51 Franklin Street, Fifth Floor
// * Boston, MA  02110-1301  USA
// */
//
//import java.lang.annotation.Annotation;
//import java.util.ArrayList;
//import java.util.Arrays;
//import java.util.Collection;
//import java.util.EnumSet;
//import java.util.HashMap;
//import java.util.HashSet;
//import java.util.Iterator;
//import java.util.List;
//import java.util.Map;
//import java.util.Properties;
//import java.util.Set;
//
//import javax.persistence.Basic;
//import javax.persistence.Cacheable;
//import javax.persistence.CollectionTable;
//import javax.persistence.Column;
//import javax.persistence.DiscriminatorType;
//import javax.persistence.DiscriminatorValue;
//import javax.persistence.ElementCollection;
//import javax.persistence.Embeddable;
//import javax.persistence.Embedded;
//import javax.persistence.EmbeddedId;
//import javax.persistence.Entity;
//import javax.persistence.FetchType;
//import javax.persistence.GeneratedValue;
//import javax.persistence.GenerationType;
//import javax.persistence.Id;
//import javax.persistence.IdClass;
//import javax.persistence.InheritanceType;
//import javax.persistence.JoinColumn;
//import javax.persistence.JoinTable;
//import javax.persistence.ManyToMany;
//import javax.persistence.ManyToOne;
//import javax.persistence.MapKey;
//import javax.persistence.MapKeyColumn;
//import javax.persistence.MapKeyJoinColumn;
//import javax.persistence.MapKeyJoinColumns;
//import javax.persistence.MappedSuperclass;
//import javax.persistence.MapsId;
//import javax.persistence.NamedNativeQueries;
//import javax.persistence.NamedNativeQuery;
//import javax.persistence.NamedQueries;
//import javax.persistence.NamedQuery;
//import javax.persistence.OneToMany;
//import javax.persistence.OneToOne;
//import javax.persistence.OrderColumn;
//import javax.persistence.PrimaryKeyJoinColumn;
//import javax.persistence.PrimaryKeyJoinColumns;
//import javax.persistence.SequenceGenerator;
//import javax.persistence.SharedCacheMode;
//import javax.persistence.SqlResultSetMapping;
//import javax.persistence.SqlResultSetMappings;
//import javax.persistence.Table;
//import javax.persistence.TableGenerator;
//import javax.persistence.UniqueConstraint;
//import javax.persistence.Version;
//
//import org.hibernate.AnnotationException;
//import org.hibernate.AssertionFailure;
//import org.hibernate.EntityMode;
//import org.hibernate.FetchMode;
//import org.hibernate.MappingException;
//import org.hibernate.annotations.BatchSize;
//import org.hibernate.annotations.Cache;
//import org.hibernate.annotations.CacheConcurrencyStrategy;
//import org.hibernate.annotations.Cascade;
//import org.hibernate.annotations.CascadeType;
//import org.hibernate.annotations.Check;
//import org.hibernate.annotations.CollectionId;
//import org.hibernate.annotations.CollectionOfElements;
//import org.hibernate.annotations.Columns;
//import org.hibernate.annotations.DiscriminatorOptions;
//import org.hibernate.annotations.Fetch;
//import org.hibernate.annotations.FetchProfile;
//import org.hibernate.annotations.FetchProfiles;
//import org.hibernate.annotations.Filter;
//import org.hibernate.annotations.FilterDef;
//import org.hibernate.annotations.FilterDefs;
//import org.hibernate.annotations.Filters;
//import org.hibernate.annotations.ForceDiscriminator;
//import org.hibernate.annotations.ForeignKey;
//import org.hibernate.annotations.Formula;
//import org.hibernate.annotations.GenericGenerator;
//import org.hibernate.annotations.GenericGenerators;
//import org.hibernate.annotations.Index;
//import org.hibernate.annotations.IndexColumn;
//import org.hibernate.annotations.LazyToOne;
//import org.hibernate.annotations.LazyToOneOption;
//import org.hibernate.annotations.ManyToAny;
//import org.hibernate.annotations.MapKeyType;
//import org.hibernate.annotations.NaturalId;
//import org.hibernate.annotations.NotFound;
//import org.hibernate.annotations.NotFoundAction;
//import org.hibernate.annotations.OnDelete;
//import org.hibernate.annotations.OnDeleteAction;
//import org.hibernate.annotations.OrderBy;
//import org.hibernate.annotations.ParamDef;
//import org.hibernate.annotations.Parameter;
//import org.hibernate.annotations.Parent;
//import org.hibernate.annotations.Proxy;
//import org.hibernate.annotations.Sort;
//import org.hibernate.annotations.Source;
//import org.hibernate.annotations.Tuplizer;
//import org.hibernate.annotations.Tuplizers;
//import org.hibernate.annotations.TypeDef;
//import org.hibernate.annotations.TypeDefs;
//import org.hibernate.annotations.Where;
//import org.hibernate.annotations.common.reflection.ReflectionManager;
//import org.hibernate.annotations.common.reflection.XAnnotatedElement;
//import org.hibernate.annotations.common.reflection.XClass;
//import org.hibernate.annotations.common.reflection.XMethod;
//import org.hibernate.annotations.common.reflection.XPackage;
//import org.hibernate.annotations.common.reflection.XProperty;
//import org.hibernate.cache.RegionFactory;
//import org.hibernate.cfg.AccessType;
//import org.hibernate.cfg.AnnotatedClassType;
//import org.hibernate.cfg.BinderHelper;
//import org.hibernate.cfg.Configuration;
//import org.hibernate.cfg.CopyIdentifierComponentSecondPass;
//import org.hibernate.cfg.CreateKeySecondPass;
//import org.hibernate.cfg.Ejb3Column;
//import org.hibernate.cfg.Ejb3DiscriminatorColumn;
//import org.hibernate.cfg.Ejb3JoinColumn;
//import org.hibernate.cfg.FkSecondPass;
//import org.hibernate.cfg.InheritanceState;
//import org.hibernate.cfg.JoinedSubclassFkSecondPass;
//import org.hibernate.cfg.Mappings;
//import org.hibernate.cfg.NotYetImplementedException;
//import org.hibernate.cfg.OneToOneSecondPass;
//import org.hibernate.cfg.PropertyData;
//import org.hibernate.cfg.PropertyHolder;
//import org.hibernate.cfg.PropertyHolderBuilder;
//import org.hibernate.cfg.PropertyInferredData;
//import org.hibernate.cfg.PropertyPreloadedData;
//import org.hibernate.cfg.SecondPass;
//import org.hibernate.cfg.SecondaryTableSecondPass;
//import org.hibernate.cfg.SettingsFactory;
//import org.hibernate.cfg.ToOneBinder;
//import org.hibernate.cfg.ToOneFkSecondPass;
//import org.hibernate.cfg.UniqueConstraintHolder;
//import org.hibernate.cfg.VerifyFetchProfileReferenceSecondPass;
//import org.hibernate.cfg.WrappedInferredData;
//import org.hibernate.cfg.annotations.CollectionBinder;
//import org.hibernate.cfg.annotations.EntityBinder;
//import org.hibernate.cfg.annotations.MapKeyColumnDelegator;
//import org.hibernate.cfg.annotations.MapKeyJoinColumnDelegator;
//import org.hibernate.cfg.annotations.Nullability;
//import org.hibernate.cfg.annotations.PropertyBinder;
//import org.hibernate.cfg.annotations.QueryBinder;
//import org.hibernate.cfg.annotations.SimpleValueBinder;
//import org.hibernate.cfg.annotations.TableBinder;
//import org.hibernate.engine.FilterDefinition;
//import org.hibernate.engine.Versioning;
//import org.hibernate.id.MultipleHiLoPerTableGenerator;
//import org.hibernate.id.PersistentIdentifierGenerator;
//import org.hibernate.id.SequenceHiLoGenerator;
//import org.hibernate.id.TableHiLoGenerator;
//import org.hibernate.id.enhanced.SequenceStyleGenerator;
//import org.hibernate.mapping.Any;
//import org.hibernate.mapping.Component;
//import org.hibernate.mapping.DependantValue;
//import org.hibernate.mapping.IdGenerator;
//import org.hibernate.mapping.Join;
//import org.hibernate.mapping.JoinedSubclass;
//import org.hibernate.mapping.KeyValue;
//import org.hibernate.mapping.PersistentClass;
//import org.hibernate.mapping.Property;
//import org.hibernate.mapping.RootClass;
//import org.hibernate.mapping.SimpleValue;
//import org.hibernate.mapping.SingleTableSubclass;
//import org.hibernate.mapping.Subclass;
//import org.hibernate.mapping.ToOne;
//import org.hibernate.mapping.UnionSubclass;
//import org.hibernate.persister.entity.JoinedSubclassEntityPersister;
//import org.hibernate.persister.entity.SingleTableEntityPersister;
//import org.hibernate.persister.entity.UnionSubclassEntityPersister;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//
///**
// * JSR 175 annotation binder which reads the annotations from classes, applies
// * the principles of the EJB3 spec and produces the Hibernate configuration-time
// * metamodel (the classes in the {@code org.hibernate.mapping} package)
// * 
// * @author Emmanuel Bernard
// * @author Hardy Ferentschik
// */
//@SuppressWarnings("unchecked")
//public final class MyAnnotationBinder {
//
//	/*
//	 * Some design description I tried to remove any link to annotation except
//	 * from the 2 first level of method call. It'll enable to: - facilitate
//	 * annotation overriding - mutualize one day xml and annotation binder
//	 * (probably a dream though) - split this huge class in smaller mapping
//	 * oriented classes
//	 * 
//	 * bindSomething usually create the mapping container and is accessed by one
//	 * of the 2 first level method makeSomething usually create the mapping
//	 * container and is accessed by bindSomething[else] fillSomething take the
//	 * container into parameter and fill it.
//	 */
//
//	private MyAnnotationBinder() {
//	}
//
//	private static final Logger log = LoggerFactory
//			.getLogger(MyAnnotationBinder.class);
//
//	public static void bindDefaults(Mappings mappings) {
//		Map defaults = mappings.getReflectionManager().getDefaults();
//		{
//			List<SequenceGenerator> anns = (List<SequenceGenerator>) defaults
//					.get(SequenceGenerator.class);
//			if (anns != null) {
//				for (SequenceGenerator ann : anns) {
//					IdGenerator idGen = buildIdGenerator(ann, mappings);
//					if (idGen != null) {
//						mappings.addDefaultGenerator(idGen);
//					}
//				}
//			}
//		}
//		{
//			List<TableGenerator> anns = (List<TableGenerator>) defaults
//					.get(TableGenerator.class);
//			if (anns != null) {
//				for (TableGenerator ann : anns) {
//					IdGenerator idGen = buildIdGenerator(ann, mappings);
//					if (idGen != null) {
//						mappings.addDefaultGenerator(idGen);
//					}
//				}
//			}
//		}
//		{
//			List<NamedQuery> anns = (List<NamedQuery>) defaults
//					.get(NamedQuery.class);
//			if (anns != null) {
//				for (NamedQuery ann : anns) {
//					QueryBinder.bindQuery(ann, mappings, true);
//				}
//			}
//		}
//		{
//			List<NamedNativeQuery> anns = (List<NamedNativeQuery>) defaults
//					.get(NamedNativeQuery.class);
//			if (anns != null) {
//				for (NamedNativeQuery ann : anns) {
//					QueryBinder.bindNativeQuery(ann, mappings, true);
//				}
//			}
//		}
//		{
//			List<SqlResultSetMapping> anns = (List<SqlResultSetMapping>) defaults
//					.get(SqlResultSetMapping.class);
//			if (anns != null) {
//				for (SqlResultSetMapping ann : anns) {
//					QueryBinder.bindSqlResultsetMapping(ann, mappings, true);
//				}
//			}
//		}
//	}
//
//	public static void bindPackage(String packageName, Mappings mappings) {
//		XPackage pckg;
//		try {
//			pckg = mappings.getReflectionManager().packageForName(packageName);
//		} catch (ClassNotFoundException cnf) {
//			log.warn("Package not found or wo package-info.java: {}",
//					packageName);
//			return;
//		}
//		if (pckg.isAnnotationPresent(SequenceGenerator.class)) {
//			SequenceGenerator ann = pckg.getAnnotation(SequenceGenerator.class);
//			IdGenerator idGen = buildIdGenerator(ann, mappings);
//			mappings.addGenerator(idGen);
//			log.trace("Add sequence generator with name: {}", idGen.getName());
//		}
//		if (pckg.isAnnotationPresent(TableGenerator.class)) {
//			TableGenerator ann = pckg.getAnnotation(TableGenerator.class);
//			IdGenerator idGen = buildIdGenerator(ann, mappings);
//			mappings.addGenerator(idGen);
//
//		}
//		bindGenericGenerators(pckg, mappings);
//		bindQueries(pckg, mappings);
//		bindFilterDefs(pckg, mappings);
//		bindTypeDefs(pckg, mappings);
//		bindFetchProfiles(pckg, mappings);
//		BinderHelper.bindAnyMetaDefs(pckg, mappings);
//	}
//
//	private static void bindGenericGenerators(
//			XAnnotatedElement annotatedElement, Mappings mappings) {
//		GenericGenerator defAnn = annotatedElement
//				.getAnnotation(GenericGenerator.class);
//		GenericGenerators defsAnn = annotatedElement
//				.getAnnotation(GenericGenerators.class);
//		if (defAnn != null) {
//			bindGenericGenerator(defAnn, mappings);
//		}
//		if (defsAnn != null) {
//			for (GenericGenerator def : defsAnn.value()) {
//				bindGenericGenerator(def, mappings);
//			}
//		}
//	}
//
//	private static void bindGenericGenerator(GenericGenerator def,
//			Mappings mappings) {
//		IdGenerator idGen = buildIdGenerator(def, mappings);
//		mappings.addGenerator(idGen);
//	}
//
//	private static void bindQueries(XAnnotatedElement annotatedElement,
//			Mappings mappings) {
//		{
//			SqlResultSetMapping ann = annotatedElement
//					.getAnnotation(SqlResultSetMapping.class);
//			QueryBinder.bindSqlResultsetMapping(ann, mappings, false);
//		}
//		{
//			SqlResultSetMappings ann = annotatedElement
//					.getAnnotation(SqlResultSetMappings.class);
//			if (ann != null) {
//				for (SqlResultSetMapping current : ann.value()) {
//					QueryBinder.bindSqlResultsetMapping(current, mappings,
//							false);
//				}
//			}
//		}
//		{
//			NamedQuery ann = annotatedElement.getAnnotation(NamedQuery.class);
//			QueryBinder.bindQuery(ann, mappings, false);
//		}
//		{
//			org.hibernate.annotations.NamedQuery ann = annotatedElement
//					.getAnnotation(org.hibernate.annotations.NamedQuery.class);
//			QueryBinder.bindQuery(ann, mappings);
//		}
//		{
//			NamedQueries ann = annotatedElement
//					.getAnnotation(NamedQueries.class);
//			QueryBinder.bindQueries(ann, mappings, false);
//		}
//		{
//			org.hibernate.annotations.NamedQueries ann = annotatedElement
//					.getAnnotation(org.hibernate.annotations.NamedQueries.class);
//			QueryBinder.bindQueries(ann, mappings);
//		}
//		{
//			NamedNativeQuery ann = annotatedElement
//					.getAnnotation(NamedNativeQuery.class);
//			QueryBinder.bindNativeQuery(ann, mappings, false);
//		}
//		{
//			org.hibernate.annotations.NamedNativeQuery ann = annotatedElement
//					.getAnnotation(org.hibernate.annotations.NamedNativeQuery.class);
//			QueryBinder.bindNativeQuery(ann, mappings);
//		}
//		{
//			NamedNativeQueries ann = annotatedElement
//					.getAnnotation(NamedNativeQueries.class);
//			QueryBinder.bindNativeQueries(ann, mappings, false);
//		}
//		{
//			org.hibernate.annotations.NamedNativeQueries ann = annotatedElement
//					.getAnnotation(org.hibernate.annotations.NamedNativeQueries.class);
//			QueryBinder.bindNativeQueries(ann, mappings);
//		}
//	}
//
//	private static IdGenerator buildIdGenerator(
//			java.lang.annotation.Annotation ann, Mappings mappings) {
//		IdGenerator idGen = new IdGenerator();
//		if (mappings.getSchemaName() != null) {
//			idGen.addParam(PersistentIdentifierGenerator.SCHEMA,
//					mappings.getSchemaName());
//		}
//		if (mappings.getCatalogName() != null) {
//			idGen.addParam(PersistentIdentifierGenerator.CATALOG,
//					mappings.getCatalogName());
//		}
//		final boolean useNewGeneratorMappings = mappings
//				.useNewGeneratorMappings();
//		if (ann == null) {
//			idGen = null;
//		} else if (ann instanceof TableGenerator) {
//			TableGenerator tabGen = (TableGenerator) ann;
//			idGen.setName(tabGen.name());
//			if (useNewGeneratorMappings) {
//				idGen.setIdentifierGeneratorStrategy(org.hibernate.id.enhanced.TableGenerator.class
//						.getName());
//				idGen.addParam(
//						org.hibernate.id.enhanced.TableGenerator.CONFIG_PREFER_SEGMENT_PER_ENTITY,
//						"true");
//
//				if (!BinderHelper.isEmptyAnnotationValue(tabGen.catalog())) {
//					idGen.addParam(
//							org.hibernate.id.enhanced.TableGenerator.CATALOG,
//							tabGen.catalog());
//				}
//				if (!BinderHelper.isEmptyAnnotationValue(tabGen.schema())) {
//					idGen.addParam(
//							org.hibernate.id.enhanced.TableGenerator.SCHEMA,
//							tabGen.schema());
//				}
//				if (!BinderHelper.isEmptyAnnotationValue(tabGen.table())) {
//					idGen.addParam(
//							org.hibernate.id.enhanced.TableGenerator.TABLE_PARAM,
//							tabGen.table());
//				}
//				if (!BinderHelper.isEmptyAnnotationValue(tabGen.pkColumnName())) {
//					idGen.addParam(
//							org.hibernate.id.enhanced.TableGenerator.SEGMENT_COLUMN_PARAM,
//							tabGen.pkColumnName());
//				}
//				if (!BinderHelper
//						.isEmptyAnnotationValue(tabGen.pkColumnValue())) {
//					idGen.addParam(
//							org.hibernate.id.enhanced.TableGenerator.SEGMENT_VALUE_PARAM,
//							tabGen.pkColumnValue());
//				}
//				if (!BinderHelper.isEmptyAnnotationValue(tabGen
//						.valueColumnName())) {
//					idGen.addParam(
//							org.hibernate.id.enhanced.TableGenerator.VALUE_COLUMN_PARAM,
//							tabGen.valueColumnName());
//				}
//				idGen.addParam(
//						org.hibernate.id.enhanced.TableGenerator.INCREMENT_PARAM,
//						String.valueOf(tabGen.allocationSize()));
//				// See comment on HHH-4884 wrt initialValue. Basically
//				// initialValue is really the stated value + 1
//				idGen.addParam(
//						org.hibernate.id.enhanced.TableGenerator.INITIAL_PARAM,
//						String.valueOf(tabGen.initialValue() + 1));
//				if (tabGen.uniqueConstraints() != null
//						&& tabGen.uniqueConstraints().length > 0) {
//					log.warn(
//							"Ignoring unique constraints specified on table generator [{}]",
//							tabGen.name());
//				}
//			} else {
//				idGen.setIdentifierGeneratorStrategy(MultipleHiLoPerTableGenerator.class
//						.getName());
//
//				if (!BinderHelper.isEmptyAnnotationValue(tabGen.table())) {
//					idGen.addParam(MultipleHiLoPerTableGenerator.ID_TABLE,
//							tabGen.table());
//				}
//				if (!BinderHelper.isEmptyAnnotationValue(tabGen.catalog())) {
//					idGen.addParam(MultipleHiLoPerTableGenerator.CATALOG,
//							tabGen.catalog());
//				}
//				if (!BinderHelper.isEmptyAnnotationValue(tabGen.schema())) {
//					idGen.addParam(MultipleHiLoPerTableGenerator.SCHEMA,
//							tabGen.schema());
//				}
//				// FIXME implement uniqueconstrains
//				if (tabGen.uniqueConstraints() != null
//						&& tabGen.uniqueConstraints().length > 0) {
//					log.warn(
//							"Ignoring unique constraints specified on table generator [{}]",
//							tabGen.name());
//				}
//
//				if (!BinderHelper.isEmptyAnnotationValue(tabGen.pkColumnName())) {
//					idGen.addParam(
//							MultipleHiLoPerTableGenerator.PK_COLUMN_NAME,
//							tabGen.pkColumnName());
//				}
//				if (!BinderHelper.isEmptyAnnotationValue(tabGen
//						.valueColumnName())) {
//					idGen.addParam(
//							MultipleHiLoPerTableGenerator.VALUE_COLUMN_NAME,
//							tabGen.valueColumnName());
//				}
//				if (!BinderHelper
//						.isEmptyAnnotationValue(tabGen.pkColumnValue())) {
//					idGen.addParam(MultipleHiLoPerTableGenerator.PK_VALUE_NAME,
//							tabGen.pkColumnValue());
//				}
//				idGen.addParam(TableHiLoGenerator.MAX_LO,
//						String.valueOf(tabGen.allocationSize() - 1));
//			}
//			log.trace("Add table generator with name: {}", idGen.getName());
//		} else if (ann instanceof SequenceGenerator) {
//			SequenceGenerator seqGen = (SequenceGenerator) ann;
//			idGen.setName(seqGen.name());
//			if (useNewGeneratorMappings) {
//				idGen.setIdentifierGeneratorStrategy(SequenceStyleGenerator.class
//						.getName());
//
//				if (!BinderHelper.isEmptyAnnotationValue(seqGen.catalog())) {
//					idGen.addParam(SequenceStyleGenerator.CATALOG,
//							seqGen.catalog());
//				}
//				if (!BinderHelper.isEmptyAnnotationValue(seqGen.schema())) {
//					idGen.addParam(SequenceStyleGenerator.SCHEMA,
//							seqGen.schema());
//				}
//				if (!BinderHelper.isEmptyAnnotationValue(seqGen.sequenceName())) {
//					idGen.addParam(SequenceStyleGenerator.SEQUENCE_PARAM,
//							seqGen.sequenceName());
//				}
//				idGen.addParam(SequenceStyleGenerator.INCREMENT_PARAM,
//						String.valueOf(seqGen.allocationSize()));
//				idGen.addParam(SequenceStyleGenerator.INITIAL_PARAM,
//						String.valueOf(seqGen.initialValue()));
//			} else {
//				idGen.setIdentifierGeneratorStrategy("seqhilo");
//
//				if (!BinderHelper.isEmptyAnnotationValue(seqGen.sequenceName())) {
//					idGen.addParam(org.hibernate.id.SequenceGenerator.SEQUENCE,
//							seqGen.sequenceName());
//				}
//				// FIXME: work on initialValue() through
//				// SequenceGenerator.PARAMETERS
//				// steve : or just use o.h.id.enhanced.SequenceStyleGenerator
//				if (seqGen.initialValue() != 1) {
//					log.warn(
//							"Hibernate does not support SequenceGenerator.initialValue() unless '{}' set",
//							Configuration.USE_NEW_ID_GENERATOR_MAPPINGS);
//				}
//				idGen.addParam(SequenceHiLoGenerator.MAX_LO,
//						String.valueOf(seqGen.allocationSize() - 1));
//				log.trace("Add sequence generator with name: {}",
//						idGen.getName());
//			}
//		} else if (ann instanceof GenericGenerator) {
//			GenericGenerator genGen = (GenericGenerator) ann;
//			idGen.setName(genGen.name());
//			idGen.setIdentifierGeneratorStrategy(genGen.strategy());
//			Parameter[] params = genGen.parameters();
//			for (Parameter parameter : params) {
//				idGen.addParam(parameter.name(), parameter.value());
//			}
//			log.trace("Add generic generator with name: {}", idGen.getName());
//		} else {
//			throw new AssertionFailure("Unknown Generator annotation: " + ann);
//		}
//		return idGen;
//	}
//
//	/**
//	 * Bind a class having JSR175 annotations. Subclasses <b>have to</b> be
//	 * bound after its parent class.
//	 * 
//	 * @param clazzToProcess
//	 *            entity to bind as {@code XClass} instance
//	 * @param inheritanceStatePerClass
//	 *            Meta data about the inheritance relationships for all mapped
//	 *            classes
//	 * @param mappings
//	 *            Mapping meta data
//	 * 
//	 * @throws MappingException
//	 *             in case there is an configuration error
//	 */
//	public static void bindClass(XClass clazzToProcess,
//			Map<XClass, InheritanceState> inheritanceStatePerClass,
//			Mappings mappings) throws MappingException {
//		// @Entity and @MappedSuperclass on the same class leads to a NPE down
//		// the road
//		if (clazzToProcess.isAnnotationPresent(Entity.class)
//				&& clazzToProcess.isAnnotationPresent(MappedSuperclass.class)) {
//			throw new AnnotationException(
//					"An entity cannot be annotated with both @Entity and @MappedSuperclass: "
//							+ clazzToProcess.getName());
//		}
//
//		// TODO: be more strict with secondarytable allowance (not for ids, not
//		// for secondary table join columns etc)
//		InheritanceState inheritanceState = inheritanceStatePerClass
//				.get(clazzToProcess);
//		AnnotatedClassType classType = mappings.getClassType(clazzToProcess);
//
//		// Queries declared in MappedSuperclass should be usable in Subclasses
//		if (AnnotatedClassType.EMBEDDABLE_SUPERCLASS.equals(classType)) {
//			bindQueries(clazzToProcess, mappings);
//			bindTypeDefs(clazzToProcess, mappings);
//			bindFilterDefs(clazzToProcess, mappings);
//		}
//
//		if (!isEntityClassType(clazzToProcess, classType)) {
//			return;
//		}
//
//		log.info("Binding entity from annotated class: {}",
//				clazzToProcess.getName());
//
//		PersistentClass superEntity = getSuperEntity(clazzToProcess,
//				inheritanceStatePerClass, mappings, inheritanceState);
//
//		PersistentClass persistentClass = makePersistentClass(inheritanceState,
//				superEntity);
//		Entity entityAnn = clazzToProcess.getAnnotation(Entity.class);
//		org.hibernate.annotations.Entity hibEntityAnn = clazzToProcess
//				.getAnnotation(org.hibernate.annotations.Entity.class);
//		EntityBinder entityBinder = new EntityBinder(entityAnn, hibEntityAnn,
//				clazzToProcess, persistentClass, mappings);
//		entityBinder.setInheritanceState(inheritanceState);
//
//		bindQueries(clazzToProcess, mappings);
//		bindFilterDefs(clazzToProcess, mappings);
//		bindTypeDefs(clazzToProcess, mappings);
//		bindFetchProfiles(clazzToProcess, mappings);
//		BinderHelper.bindAnyMetaDefs(clazzToProcess, mappings);
//
//		String schema = "";
//		String table = ""; // might be no @Table annotation on the annotated
//							// class
//		String catalog = "";
//		List<UniqueConstraintHolder> uniqueConstraints = new ArrayList<UniqueConstraintHolder>();
//		if (clazzToProcess.isAnnotationPresent(javax.persistence.Table.class)) {
//			javax.persistence.Table tabAnn = clazzToProcess
//					.getAnnotation(javax.persistence.Table.class);
//			table = tabAnn.name();
//			schema = tabAnn.schema();
//			catalog = tabAnn.catalog();
//			uniqueConstraints = TableBinder.buildUniqueConstraintHolders(tabAnn
//					.uniqueConstraints());
//		}
//
//		Ejb3JoinColumn[] inheritanceJoinedColumns = makeInheritanceJoinColumns(
//				clazzToProcess, mappings, inheritanceState, superEntity);
//		Ejb3DiscriminatorColumn discriminatorColumn = null;
//		if (InheritanceType.SINGLE_TABLE.equals(inheritanceState.getType())) {
//			discriminatorColumn = processDiscriminatorProperties(
//					clazzToProcess, mappings, inheritanceState, entityBinder);
//		}
//
//		entityBinder.setProxy(clazzToProcess.getAnnotation(Proxy.class));
//		entityBinder
//				.setBatchSize(clazzToProcess.getAnnotation(BatchSize.class));
//		entityBinder.setWhere(clazzToProcess.getAnnotation(Where.class));
//		entityBinder.setCache(determineCacheSettings(clazzToProcess, mappings));
//
//		// Filters are not allowed on subclasses
//		if (!inheritanceState.hasParents()) {
//			bindFilters(clazzToProcess, entityBinder, mappings);
//		}
//
//		entityBinder.bindEntity();
//
//		if (inheritanceState.hasTable()) {
//			Check checkAnn = clazzToProcess.getAnnotation(Check.class);
//			String constraints = checkAnn == null ? null : checkAnn
//					.constraints();
//			entityBinder.bindTable(
//					schema,
//					catalog,
//					table,
//					uniqueConstraints,
//					constraints,
//					inheritanceState.hasDenormalizedTable() ? superEntity
//							.getTable() : null);
//		} else {
//			if (clazzToProcess.isAnnotationPresent(Table.class)) {
//				log.warn("Illegal use of @Table in a subclass of a SINGLE_TABLE hierarchy: "
//						+ clazzToProcess.getName());
//			}
//		}
//
//		PropertyHolder propertyHolder = PropertyHolderBuilder
//				.buildPropertyHolder(clazzToProcess, persistentClass,
//						entityBinder, mappings, inheritanceStatePerClass);
//
//		javax.persistence.SecondaryTable secTabAnn = clazzToProcess
//				.getAnnotation(javax.persistence.SecondaryTable.class);
//		javax.persistence.SecondaryTables secTabsAnn = clazzToProcess
//				.getAnnotation(javax.persistence.SecondaryTables.class);
//		entityBinder.firstLevelSecondaryTablesBinding(secTabAnn, secTabsAnn);
//
//		OnDelete onDeleteAnn = clazzToProcess.getAnnotation(OnDelete.class);
//		boolean onDeleteAppropriate = false;
//		if (InheritanceType.JOINED.equals(inheritanceState.getType())
//				&& inheritanceState.hasParents()) {
//			onDeleteAppropriate = true;
//			final JoinedSubclass jsc = (JoinedSubclass) persistentClass;
//			if (persistentClass.getEntityPersisterClass() == null) {
//				persistentClass.getRootClass().setEntityPersisterClass(
//						JoinedSubclassEntityPersister.class);
//			}
//			SimpleValue key = new DependantValue(mappings, jsc.getTable(),
//					jsc.getIdentifier());
//			jsc.setKey(key);
//			ForeignKey fk = clazzToProcess.getAnnotation(ForeignKey.class);
//			if (fk != null && !BinderHelper.isEmptyAnnotationValue(fk.name())) {
//				key.setForeignKeyName(fk.name());
//			}
//			if (onDeleteAnn != null) {
//				key.setCascadeDeleteEnabled(OnDeleteAction.CASCADE
//						.equals(onDeleteAnn.action()));
//			} else {
//				key.setCascadeDeleteEnabled(false);
//			}
//			// we are never in a second pass at that stage, so queue it
//			SecondPass sp = new JoinedSubclassFkSecondPass(jsc,
//					inheritanceJoinedColumns, key, mappings);
//			mappings.addSecondPass(sp);
//			mappings.addSecondPass(new CreateKeySecondPass(jsc));
//
//		} else if (InheritanceType.SINGLE_TABLE.equals(inheritanceState
//				.getType())) {
//			if (inheritanceState.hasParents()) {
//				if (persistentClass.getEntityPersisterClass() == null) {
//					persistentClass.getRootClass().setEntityPersisterClass(
//							SingleTableEntityPersister.class);
//				}
//			} else {
//				if (inheritanceState.hasSiblings()
//						|| !discriminatorColumn.isImplicit()) {
//					// need a discriminator column
//					bindDiscriminatorToPersistentClass(
//							(RootClass) persistentClass, discriminatorColumn,
//							entityBinder.getSecondaryTables(), propertyHolder,
//							mappings);
//					entityBinder.bindDiscriminatorValue();// bind it again since
//															// the type might
//															// have changed
//				}
//			}
//		} else if (InheritanceType.TABLE_PER_CLASS.equals(inheritanceState
//				.getType())) {
//			if (inheritanceState.hasParents()) {
//				if (persistentClass.getEntityPersisterClass() == null) {
//					persistentClass.getRootClass().setEntityPersisterClass(
//							UnionSubclassEntityPersister.class);
//				}
//			}
//		}
//		if (onDeleteAnn != null && !onDeleteAppropriate) {
//			log.warn(
//					"Inapropriate use of @OnDelete on entity, annotation ignored: {}",
//					propertyHolder.getEntityName());
//		}
//
//		// try to find class level generators
//		HashMap<String, IdGenerator> classGenerators = buildLocalGenerators(
//				clazzToProcess, mappings);
//
//		// check properties
//		final InheritanceState.ElementsToProcess elementsToProcess = inheritanceState
//				.getElementsToProcess();
//		inheritanceState.postProcess(persistentClass, entityBinder);
//
//		final boolean subclassAndSingleTableStrategy = inheritanceState
//				.getType() == InheritanceType.SINGLE_TABLE
//				&& inheritanceState.hasParents();
//		Set<String> idPropertiesIfIdClass = new HashSet<String>();
//		boolean isIdClass = mapAsIdClass(inheritanceStatePerClass,
//				inheritanceState, persistentClass, entityBinder,
//				propertyHolder, elementsToProcess, idPropertiesIfIdClass,
//				mappings);
//
//		if (!isIdClass) {
//			entityBinder.setWrapIdsInEmbeddedComponents(elementsToProcess
//					.getIdPropertyCount() > 1);
//		}
//
//		processIdPropertiesIfNotAlready(inheritanceStatePerClass, mappings,
//				persistentClass, entityBinder, propertyHolder, classGenerators,
//				elementsToProcess, subclassAndSingleTableStrategy,
//				idPropertiesIfIdClass);
//
//		if (!inheritanceState.hasParents()) {
//			final RootClass rootClass = (RootClass) persistentClass;
//			mappings.addSecondPass(new CreateKeySecondPass(rootClass));
//		} else {
//			superEntity.addSubclass((Subclass) persistentClass);
//		}
//
//		mappings.addClass(persistentClass);
//
//		// Process secondary tables and complementary definitions (ie
//		// o.h.a.Table)
//		mappings.addSecondPass(new SecondaryTableSecondPass(entityBinder,
//				propertyHolder, clazzToProcess));
//
//		// add process complementary Table definition (index & all)
//		entityBinder.processComplementaryTableDefinitions(clazzToProcess
//				.getAnnotation(org.hibernate.annotations.Table.class));
//		entityBinder.processComplementaryTableDefinitions(clazzToProcess
//				.getAnnotation(org.hibernate.annotations.Tables.class));
//
//	}
//
//	// parse everything discriminator column relevant in case of single table
//	// inheritance
//	private static Ejb3DiscriminatorColumn processDiscriminatorProperties(
//			XClass clazzToProcess, Mappings mappings,
//			InheritanceState inheritanceState, EntityBinder entityBinder) {
//		Ejb3DiscriminatorColumn discriminatorColumn = null;
//		javax.persistence.DiscriminatorColumn discAnn = clazzToProcess
//				.getAnnotation(javax.persistence.DiscriminatorColumn.class);
//		DiscriminatorType discriminatorType = discAnn != null ? discAnn
//				.discriminatorType() : DiscriminatorType.STRING;
//
//		org.hibernate.annotations.DiscriminatorFormula discFormulaAnn = clazzToProcess
//				.getAnnotation(org.hibernate.annotations.DiscriminatorFormula.class);
//		if (!inheritanceState.hasParents()) {
//			discriminatorColumn = Ejb3DiscriminatorColumn
//					.buildDiscriminatorColumn(discriminatorType, discAnn,
//							discFormulaAnn, mappings);
//		}
//		if (discAnn != null && inheritanceState.hasParents()) {
//			log.warn(
//					"Discriminator column has to be defined in the root entity, it will be ignored in subclass: {}",
//					clazzToProcess.getName());
//		}
//
//		String discrimValue = clazzToProcess
//				.isAnnotationPresent(DiscriminatorValue.class) ? clazzToProcess
//				.getAnnotation(DiscriminatorValue.class).value() : null;
//		entityBinder.setDiscriminatorValue(discrimValue);
//
//		if (clazzToProcess.isAnnotationPresent(ForceDiscriminator.class)) {
//			log.warn("@ForceDiscriminator is deprecated use @DiscriminatorOptions instead.");
//			entityBinder.setForceDiscriminator(true);
//		}
//
//		DiscriminatorOptions discriminatorOptions = clazzToProcess
//				.getAnnotation(DiscriminatorOptions.class);
//		if (discriminatorOptions != null) {
//			entityBinder.setForceDiscriminator(discriminatorOptions.force());
//			entityBinder.setInsertableDiscriminator(discriminatorOptions
//					.insert());
//		}
//
//		return discriminatorColumn;
//	}
//
//	private static void processIdPropertiesIfNotAlready(
//			Map<XClass, InheritanceState> inheritanceStatePerClass,
//			Mappings mappings, PersistentClass persistentClass,
//			EntityBinder entityBinder, PropertyHolder propertyHolder,
//			HashMap<String, IdGenerator> classGenerators,
//			InheritanceState.ElementsToProcess elementsToProcess,
//			boolean subclassAndSingleTableStrategy,
//			Set<String> idPropertiesIfIdClass) {
//		Set<String> missingIdProperties = new HashSet<String>(
//				idPropertiesIfIdClass);
//		for (PropertyData propertyAnnotatedElement : elementsToProcess
//				.getElements()) {
//			String propertyName = propertyAnnotatedElement.getPropertyName();
//			if (!idPropertiesIfIdClass.contains(propertyName)) {
//				processElementAnnotations(
//						propertyHolder,
//						subclassAndSingleTableStrategy ? Nullability.FORCED_NULL
//								: Nullability.NO_CONSTRAINT,
//						propertyAnnotatedElement, classGenerators,
//						entityBinder, false, false, false, mappings,
//						inheritanceStatePerClass);
//			} else {
//				missingIdProperties.remove(propertyName);
//			}
//		}
//
//		if (missingIdProperties.size() != 0) {
//			StringBuilder missings = new StringBuilder();
//			for (String property : missingIdProperties) {
//				missings.append(property).append(", ");
//			}
//			throw new AnnotationException("Unable to find properties ("
//					+ missings.substring(0, missings.length() - 2)
//					+ ") in entity annotated with @IdClass:"
//					+ persistentClass.getEntityName());
//		}
//	}
//
//	private static boolean mapAsIdClass(
//			Map<XClass, InheritanceState> inheritanceStatePerClass,
//			InheritanceState inheritanceState, PersistentClass persistentClass,
//			EntityBinder entityBinder, PropertyHolder propertyHolder,
//			InheritanceState.ElementsToProcess elementsToProcess,
//			Set<String> idPropertiesIfIdClass, Mappings mappings) {
//		/*
//		 * We are looking for @IdClass In general we map the id class as
//		 * identifier using the mapping metadata of the main entity's properties
//		 * and we create an identifier mapper containing the id properties of
//		 * the main entity
//		 * 
//		 * In JPA 2, there is a shortcut if the id class is the Pk of the
//		 * associated class pointed to by the id it ought to be treated as an
//		 * embedded and not a real IdClass (at least in the Hibernate's internal
//		 * way
//		 */
//		XClass classWithIdClass = inheritanceState.getClassWithIdClass(false);
//		if (classWithIdClass != null) {
//			IdClass idClass = classWithIdClass.getAnnotation(IdClass.class);
//			XClass compositeClass = mappings.getReflectionManager().toXClass(
//					idClass.value());
//			PropertyData inferredData = new PropertyPreloadedData(
//					entityBinder.getPropertyAccessType(), "id", compositeClass);
//			PropertyData baseInferredData = new PropertyPreloadedData(
//					entityBinder.getPropertyAccessType(), "id",
//					classWithIdClass);
//			AccessType propertyAccessor = entityBinder
//					.getPropertyAccessor(compositeClass);
//			// In JPA 2, there is a shortcut if the IdClass is the Pk of the
//			// associated class pointed to by the id
//			// it ought to be treated as an embedded and not a real IdClass (at
//			// least in the Hibernate's internal way
//			final boolean isFakeIdClass = isIdClassPkOfTheAssociatedEntity(
//					elementsToProcess, compositeClass, inferredData,
//					baseInferredData, propertyAccessor,
//					inheritanceStatePerClass, mappings);
//
//			if (isFakeIdClass) {
//				return false;
//			}
//
//			boolean isComponent = true;
//			String generatorType = "assigned";
//			String generator = BinderHelper.ANNOTATION_STRING_DEFAULT;
//
//			boolean ignoreIdAnnotations = entityBinder.isIgnoreIdAnnotations();
//			entityBinder.setIgnoreIdAnnotations(true);
//			propertyHolder.setInIdClass(true);
//			bindIdClass(generatorType, generator, inferredData,
//					baseInferredData, null, propertyHolder, isComponent,
//					propertyAccessor, entityBinder, true, false, mappings,
//					inheritanceStatePerClass);
//			propertyHolder.setInIdClass(null);
//			inferredData = new PropertyPreloadedData(propertyAccessor,
//					"_identifierMapper", compositeClass);
//			Component mapper = fillComponent(propertyHolder, inferredData,
//					baseInferredData, propertyAccessor, false, entityBinder,
//					true, true, false, mappings, inheritanceStatePerClass);
//			entityBinder.setIgnoreIdAnnotations(ignoreIdAnnotations);
//			persistentClass.setIdentifierMapper(mapper);
//
//			// If id definition is on a mapped superclass, update the mapping
//			final org.hibernate.mapping.MappedSuperclass superclass = BinderHelper
//					.getMappedSuperclassOrNull(
//							inferredData.getDeclaringClass(),
//							inheritanceStatePerClass, mappings);
//			if (superclass != null) {
//				superclass.setDeclaredIdentifierMapper(mapper);
//			} else {
//				// we are for sure on the entity
//				persistentClass.setDeclaredIdentifierMapper(mapper);
//			}
//
//			Property property = new Property();
//			property.setName("_identifierMapper");
//			property.setNodeName("id");
//			property.setUpdateable(false);
//			property.setInsertable(false);
//			property.setValue(mapper);
//			property.setPropertyAccessorName("embedded");
//			persistentClass.addProperty(property);
//			entityBinder.setIgnoreIdAnnotations(true);
//
//			Iterator properties = mapper.getPropertyIterator();
//			while (properties.hasNext()) {
//				idPropertiesIfIdClass.add(((Property) properties.next())
//						.getName());
//			}
//			return true;
//		} else {
//			return false;
//		}
//	}
//
//	private static boolean isIdClassPkOfTheAssociatedEntity(
//			InheritanceState.ElementsToProcess elementsToProcess,
//			XClass compositeClass, PropertyData inferredData,
//			PropertyData baseInferredData, AccessType propertyAccessor,
//			Map<XClass, InheritanceState> inheritanceStatePerClass,
//			Mappings mappings) {
//		if (elementsToProcess.getIdPropertyCount() == 1) {
//			final PropertyData idPropertyOnBaseClass = getUniqueIdPropertyFromBaseClass(
//					inferredData, baseInferredData, propertyAccessor, mappings);
//			final InheritanceState state = inheritanceStatePerClass
//					.get(idPropertyOnBaseClass.getClassOrElement());
//			if (state == null) {
//				return false; // while it is likely a user error, let's consider
//								// it is something that might happen
//			}
//			final XClass associatedClassWithIdClass = state
//					.getClassWithIdClass(true);
//			if (associatedClassWithIdClass == null) {
//				// we cannot know for sure here unless we try and find the
//				// @EmbeddedId
//				// Let's not do this thorough checking but do some extra
//				// validation
//				final XProperty property = idPropertyOnBaseClass.getProperty();
//				return property.isAnnotationPresent(ManyToOne.class)
//						|| property.isAnnotationPresent(OneToOne.class);
//
//			} else {
//				final XClass idClass = mappings.getReflectionManager()
//						.toXClass(
//								associatedClassWithIdClass.getAnnotation(
//										IdClass.class).value());
//				return idClass.equals(compositeClass);
//			}
//		} else {
//			return false;
//		}
//	}
//
//	private static Cache determineCacheSettings(XClass clazzToProcess,
//			Mappings mappings) {
//		Cache cacheAnn = clazzToProcess.getAnnotation(Cache.class);
//		if (cacheAnn != null) {
//			return cacheAnn;
//		}
//
//		Cacheable cacheableAnn = clazzToProcess.getAnnotation(Cacheable.class);
//		SharedCacheMode mode = determineSharedCacheMode(mappings);
//		switch (mode) {
//		case ALL: {
//			cacheAnn = buildCacheMock(clazzToProcess.getName(), mappings);
//			break;
//		}
//		case ENABLE_SELECTIVE: {
//			if (cacheableAnn != null && cacheableAnn.value()) {
//				cacheAnn = buildCacheMock(clazzToProcess.getName(), mappings);
//			}
//			break;
//		}
//		case DISABLE_SELECTIVE: {
//			if (cacheableAnn == null || cacheableAnn.value()) {
//				cacheAnn = buildCacheMock(clazzToProcess.getName(), mappings);
//			}
//			break;
//		}
//		default: {
//			// treat both NONE and UNSPECIFIED the same
//			break;
//		}
//		}
//		return cacheAnn;
//	}
//
//	private static SharedCacheMode determineSharedCacheMode(Mappings mappings) {
//		SharedCacheMode mode;
//		final Object value = mappings.getConfigurationProperties().get(
//				"javax.persistence.sharedCache.mode");
//		if (value == null) {
//			log.debug("no value specified for 'javax.persistence.sharedCache.mode'; using UNSPECIFIED");
//			mode = SharedCacheMode.UNSPECIFIED;
//		} else {
//			if (SharedCacheMode.class.isInstance(value)) {
//				mode = (SharedCacheMode) value;
//			} else {
//				try {
//					mode = SharedCacheMode.valueOf(value.toString());
//				} catch (Exception e) {
//					log.debug("Unable to resolve given mode name ["
//							+ value.toString() + "]; using UNSPECIFIED : "
//							+ e.toString());
//					mode = SharedCacheMode.UNSPECIFIED;
//				}
//			}
//		}
//		return mode;
//	}
//
//	private static Cache buildCacheMock(String region, Mappings mappings) {
//		return new LocalCacheAnnotationImpl(region,
//				determineCacheConcurrencyStrategy(mappings));
//	}
//
//	private static CacheConcurrencyStrategy DEFAULT_CACHE_CONCURRENCY_STRATEGY;
//
//	static void prepareDefaultCacheConcurrencyStrategy(Properties properties) {
//		if (DEFAULT_CACHE_CONCURRENCY_STRATEGY != null) {
//			log.trace("Default cache concurrency strategy already defined");
//			return;
//		}
//
//		if (!properties
//				.containsKey(Configuration.DEFAULT_CACHE_CONCURRENCY_STRATEGY)) {
//			log.trace("Given properties did not contain any default cache concurrency strategy setting");
//			return;
//		}
//
//		final String strategyName = properties
//				.getProperty(Configuration.DEFAULT_CACHE_CONCURRENCY_STRATEGY);
//		log.trace("Discovered default cache concurrency strategy via config ["
//				+ strategyName + "]");
//		CacheConcurrencyStrategy strategy = CacheConcurrencyStrategy
//				.parse(strategyName);
//		if (strategy == null) {
//			log.trace("Discovered default cache concurrency strategy specified nothing");
//			return;
//		}
//
//		log.debug("Setting default cache concurrency strategy via config ["
//				+ strategy.name() + "]");
//		DEFAULT_CACHE_CONCURRENCY_STRATEGY = strategy;
//	}
//
//	private static CacheConcurrencyStrategy determineCacheConcurrencyStrategy(
//			Mappings mappings) {
//		if (DEFAULT_CACHE_CONCURRENCY_STRATEGY == null) {
//			final RegionFactory cacheRegionFactory = SettingsFactory
//					.createRegionFactory(mappings.getConfigurationProperties(),
//							true);
//			DEFAULT_CACHE_CONCURRENCY_STRATEGY = CacheConcurrencyStrategy
//					.fromAccessType(cacheRegionFactory.getDefaultAccessType());
//		}
//		return DEFAULT_CACHE_CONCURRENCY_STRATEGY;
//	}
//
//	@SuppressWarnings({ "ClassExplicitlyAnnotation" })
//	private static class LocalCacheAnnotationImpl implements Cache {
//		private final String region;
//		private final CacheConcurrencyStrategy usage;
//
//		private LocalCacheAnnotationImpl(String region,
//				CacheConcurrencyStrategy usage) {
//			this.region = region;
//			this.usage = usage;
//		}
//
//		public CacheConcurrencyStrategy usage() {
//			return usage;
//		}
//
//		public String region() {
//			return region;
//		}
//
//		public String include() {
//			return "all";
//		}
//
//		public Class<? extends Annotation> annotationType() {
//			return Cache.class;
//		}
//	}
//
//	private static PersistentClass makePersistentClass(
//			InheritanceState inheritanceState, PersistentClass superEntity) {
//		// we now know what kind of persistent entity it is
//		PersistentClass persistentClass;
//		// create persistent class
//		if (!inheritanceState.hasParents()) {
//			persistentClass = new RootClass();
//		} else if (InheritanceType.SINGLE_TABLE.equals(inheritanceState
//				.getType())) {
//			persistentClass = new SingleTableSubclass(superEntity);
//		} else if (InheritanceType.JOINED.equals(inheritanceState.getType())) {
//			persistentClass = new JoinedSubclass(superEntity);
//		} else if (InheritanceType.TABLE_PER_CLASS.equals(inheritanceState
//				.getType())) {
//			persistentClass = new UnionSubclass(superEntity);
//		} else {
//			throw new AssertionFailure("Unknown inheritance type: "
//					+ inheritanceState.getType());
//		}
//		return persistentClass;
//	}
//
//	private static Ejb3JoinColumn[] makeInheritanceJoinColumns(
//			XClass clazzToProcess, Mappings mappings,
//			InheritanceState inheritanceState, PersistentClass superEntity) {
//		Ejb3JoinColumn[] inheritanceJoinedColumns = null;
//		final boolean hasJoinedColumns = inheritanceState.hasParents()
//				&& InheritanceType.JOINED.equals(inheritanceState.getType());
//		if (hasJoinedColumns) {
//			// @Inheritance(JOINED) subclass need to link back to the super
//			// entity
//			PrimaryKeyJoinColumns jcsAnn = clazzToProcess
//					.getAnnotation(PrimaryKeyJoinColumns.class);
//			boolean explicitInheritanceJoinedColumns = jcsAnn != null
//					&& jcsAnn.value().length != 0;
//			if (explicitInheritanceJoinedColumns) {
//				int nbrOfInhJoinedColumns = jcsAnn.value().length;
//				PrimaryKeyJoinColumn jcAnn;
//				inheritanceJoinedColumns = new Ejb3JoinColumn[nbrOfInhJoinedColumns];
//				for (int colIndex = 0; colIndex < nbrOfInhJoinedColumns; colIndex++) {
//					jcAnn = jcsAnn.value()[colIndex];
//					inheritanceJoinedColumns[colIndex] = Ejb3JoinColumn
//							.buildJoinColumn(jcAnn, null,
//									superEntity.getIdentifier(),
//									(Map<String, Join>) null,
//									(PropertyHolder) null, mappings);
//				}
//			} else {
//				PrimaryKeyJoinColumn jcAnn = clazzToProcess
//						.getAnnotation(PrimaryKeyJoinColumn.class);
//				inheritanceJoinedColumns = new Ejb3JoinColumn[1];
//				inheritanceJoinedColumns[0] = Ejb3JoinColumn.buildJoinColumn(
//						jcAnn, null, superEntity.getIdentifier(),
//						(Map<String, Join>) null, (PropertyHolder) null,
//						mappings);
//			}
//			log.trace("Subclass joined column(s) created");
//		} else {
//			if (clazzToProcess.isAnnotationPresent(PrimaryKeyJoinColumns.class)
//					|| clazzToProcess
//							.isAnnotationPresent(PrimaryKeyJoinColumn.class)) {
//				log.warn("Root entity should not hold an PrimaryKeyJoinColum(s), will be ignored");
//			}
//		}
//		return inheritanceJoinedColumns;
//	}
//
//	private static PersistentClass getSuperEntity(XClass clazzToProcess,
//			Map<XClass, InheritanceState> inheritanceStatePerClass,
//			Mappings mappings, InheritanceState inheritanceState) {
//		InheritanceState superEntityState = InheritanceState
//				.getInheritanceStateOfSuperEntity(clazzToProcess,
//						inheritanceStatePerClass);
//		PersistentClass superEntity = superEntityState != null ? mappings
//				.getClass(superEntityState.getClazz().getName()) : null;
//		if (superEntity == null) {
//			// check if superclass is not a potential persistent class
//			if (inheritanceState.hasParents()) {
//				throw new AssertionFailure(
//						"Subclass has to be binded after it's mother class: "
//								+ superEntityState.getClazz().getName());
//			}
//		}
//		return superEntity;
//	}
//
//	private static boolean isEntityClassType(XClass clazzToProcess,
//			AnnotatedClassType classType) {
//		if (AnnotatedClassType.EMBEDDABLE_SUPERCLASS.equals(classType) // will
//																		// be
//																		// processed
//																		// by
//																		// their
//																		// subentities
//				|| AnnotatedClassType.NONE.equals(classType) // to be ignored
//				|| AnnotatedClassType.EMBEDDABLE.equals(classType) // allow
//																	// embeddable
//																	// element
//																	// declaration
//		) {
//			if (AnnotatedClassType.NONE.equals(classType)
//					&& clazzToProcess
//							.isAnnotationPresent(org.hibernate.annotations.Entity.class)) {
//				log.warn(
//						"Class annotated @org.hibernate.annotations.Entity but not javax.persistence.Entity "
//								+ "(most likely a user error): {}",
//						clazzToProcess.getName());
//			}
//			return false;
//		}
//
//		if (!classType.equals(AnnotatedClassType.ENTITY)) {
//			throw new AnnotationException(
//					"Annotated class should have a @javax.persistence.Entity, @javax.persistence.Embeddable or @javax.persistence.EmbeddedSuperclass annotation: "
//							+ clazzToProcess.getName());
//		}
//
//		return true;
//	}
//
//	/*
//	 * Process the filters defined on the given class, as well as all filters
//	 * defined on the MappedSuperclass(s) in the inheritance hierarchy
//	 */
//
//	private static void bindFilters(XClass annotatedClass,
//			EntityBinder entityBinder, Mappings mappings) {
//
//		bindFilters(annotatedClass, entityBinder);
//
//		XClass classToProcess = annotatedClass.getSuperclass();
//		while (classToProcess != null) {
//			AnnotatedClassType classType = mappings
//					.getClassType(classToProcess);
//			if (AnnotatedClassType.EMBEDDABLE_SUPERCLASS.equals(classType)) {
//				bindFilters(classToProcess, entityBinder);
//			}
//			classToProcess = classToProcess.getSuperclass();
//		}
//
//	}
//
//	private static void bindFilters(XAnnotatedElement annotatedElement,
//			EntityBinder entityBinder) {
//
//		Filters filtersAnn = annotatedElement.getAnnotation(Filters.class);
//		if (filtersAnn != null) {
//			for (Filter filter : filtersAnn.value()) {
//				entityBinder.addFilter(filter.name(), filter.condition());
//			}
//		}
//
//		Filter filterAnn = annotatedElement.getAnnotation(Filter.class);
//		if (filterAnn != null) {
//			entityBinder.addFilter(filterAnn.name(), filterAnn.condition());
//		}
//	}
//
//	private static void bindFilterDefs(XAnnotatedElement annotatedElement,
//			Mappings mappings) {
//		FilterDef defAnn = annotatedElement.getAnnotation(FilterDef.class);
//		FilterDefs defsAnn = annotatedElement.getAnnotation(FilterDefs.class);
//		if (defAnn != null) {
//			bindFilterDef(defAnn, mappings);
//		}
//		if (defsAnn != null) {
//			for (FilterDef def : defsAnn.value()) {
//				bindFilterDef(def, mappings);
//			}
//		}
//	}
//
//	private static void bindFilterDef(FilterDef defAnn, Mappings mappings) {
//		Map<String, org.hibernate.type.Type> params = new HashMap<String, org.hibernate.type.Type>();
//		for (ParamDef param : defAnn.parameters()) {
//			params.put(param.name(),
//					mappings.getTypeResolver().heuristicType(param.type()));
//		}
//		FilterDefinition def = new FilterDefinition(defAnn.name(),
//				defAnn.defaultCondition(), params);
//		log.info("Binding filter definition: {}", def.getFilterName());
//		mappings.addFilterDefinition(def);
//	}
//
//	private static void bindTypeDefs(XAnnotatedElement annotatedElement,
//			Mappings mappings) {
//		TypeDef defAnn = annotatedElement.getAnnotation(TypeDef.class);
//		TypeDefs defsAnn = annotatedElement.getAnnotation(TypeDefs.class);
//		if (defAnn != null) {
//			bindTypeDef(defAnn, mappings);
//		}
//		if (defsAnn != null) {
//			for (TypeDef def : defsAnn.value()) {
//				bindTypeDef(def, mappings);
//			}
//		}
//	}
//
//	private static void bindFetchProfiles(XAnnotatedElement annotatedElement,
//			Mappings mappings) {
//		FetchProfile fetchProfileAnnotation = annotatedElement
//				.getAnnotation(FetchProfile.class);
//		FetchProfiles fetchProfileAnnotations = annotatedElement
//				.getAnnotation(FetchProfiles.class);
//		if (fetchProfileAnnotation != null) {
//			bindFetchProfile(fetchProfileAnnotation, mappings);
//		}
//		if (fetchProfileAnnotations != null) {
//			for (FetchProfile profile : fetchProfileAnnotations.value()) {
//				bindFetchProfile(profile, mappings);
//			}
//		}
//	}
//
//	private static void bindFetchProfile(FetchProfile fetchProfileAnnotation,
//			Mappings mappings) {
//		for (FetchProfile.FetchOverride fetch : fetchProfileAnnotation
//				.fetchOverrides()) {
//			org.hibernate.annotations.FetchMode mode = fetch.mode();
//			if (!mode.equals(org.hibernate.annotations.FetchMode.JOIN)) {
//				throw new MappingException(
//						"Only FetchMode.JOIN is currently supported");
//			}
//
//			SecondPass sp = new VerifyFetchProfileReferenceSecondPass(
//					fetchProfileAnnotation.name(), fetch, mappings);
//			mappings.addSecondPass(sp);
//		}
//	}
//
//	private static void bindTypeDef(TypeDef defAnn, Mappings mappings) {
//		Properties params = new Properties();
//		for (Parameter param : defAnn.parameters()) {
//			params.setProperty(param.name(), param.value());
//		}
//
//		if (BinderHelper.isEmptyAnnotationValue(defAnn.name())
//				&& defAnn.defaultForType().equals(void.class)) {
//			throw new AnnotationException(
//					"Either name or defaultForType (or both) attribute should be set in TypeDef having typeClass "
//							+ defAnn.typeClass().getName());
//		}
//
//		if (!BinderHelper.isEmptyAnnotationValue(defAnn.name())) {
//			log.info("Binding type definition: {}", defAnn.name());
//			mappings.addTypeDef(defAnn.name(), defAnn.typeClass().getName(),
//					params);
//		}
//		if (!defAnn.defaultForType().equals(void.class)) {
//			log.info("Binding type definition: {}", defAnn.defaultForType()
//					.getName());
//			mappings.addTypeDef(defAnn.defaultForType().getName(), defAnn
//					.typeClass().getName(), params);
//		}
//
//	}
//
//	private static void bindDiscriminatorToPersistentClass(RootClass rootClass,
//			Ejb3DiscriminatorColumn discriminatorColumn,
//			Map<String, Join> secondaryTables, PropertyHolder propertyHolder,
//			Mappings mappings) {
//		if (rootClass.getDiscriminator() == null) {
//			if (discriminatorColumn == null) {
//				throw new AssertionFailure(
//						"discriminator column should have been built");
//			}
//			discriminatorColumn.setJoins(secondaryTables);
//			discriminatorColumn.setPropertyHolder(propertyHolder);
//			SimpleValue discrim = new SimpleValue(mappings,
//					rootClass.getTable());
//			rootClass.setDiscriminator(discrim);
//			discriminatorColumn.linkWithValue(discrim);
//			discrim.setTypeName(discriminatorColumn.getDiscriminatorTypeName());
//			rootClass.setPolymorphic(true);
//			log.trace("Setting discriminator for entity {}",
//					rootClass.getEntityName());
//		}
//	}
//
//	/**
//	 * @param elements
//	 *            List of {@code ProperyData} instances
//	 * @param defaultAccessType
//	 *            The default value access strategy which has to be used in case
//	 *            no explicit local access strategy is used
//	 * @param propertyContainer
//	 *            Metadata about a class and its properties
//	 * @param mappings
//	 *            Mapping meta data
//	 * 
//	 * @return the number of id properties found while iterating the elements of
//	 *         {@code annotatedClass} using the determined access strategy,
//	 *         {@code false} otherwise.
//	 */
//	static int addElementsOfClass(List<PropertyData> elements,
//			AccessType defaultAccessType, PropertyContainer propertyContainer,
//			Mappings mappings) {
//		int idPropertyCounter = 0;
//		AccessType accessType = defaultAccessType;
//
//		if (propertyContainer.hasExplicitAccessStrategy()) {
//			accessType = propertyContainer.getExplicitAccessStrategy();
//		}
//
//		Collection<XProperty> properties = propertyContainer
//				.getProperties(accessType);
//		for (XProperty p : properties) {
//			final int currentIdPropertyCounter = addProperty(propertyContainer,
//					p, elements, accessType.getType(), mappings);
//			idPropertyCounter += currentIdPropertyCounter;
//		}
//		return idPropertyCounter;
//	}
//
//	private static int addProperty(PropertyContainer propertyContainer,
//			XProperty property, List<PropertyData> annElts,
//			String propertyAccessor, Mappings mappings) {
//		final XClass declaringClass = propertyContainer.getDeclaringClass();
//		final XClass entity = propertyContainer.getEntityAtStake();
//		int idPropertyCounter = 0;
//		PropertyData propertyAnnotatedElement = new PropertyInferredData(
//				declaringClass, property, propertyAccessor,
//				mappings.getReflectionManager());
//
//		/*
//		 * put element annotated by @Id in front since it has to be parsed
//		 * before any association by Hibernate
//		 */
//		final XAnnotatedElement element = propertyAnnotatedElement
//				.getProperty();
//		if (element.isAnnotationPresent(Id.class)
//				|| element.isAnnotationPresent(EmbeddedId.class)) {
//			annElts.add(0, propertyAnnotatedElement);
//			/**
//			 * The property must be put in hibernate.properties as it's a system
//			 * wide property. Fixable? TODO support true/false/default on the
//			 * property instead of present / not present TODO is @Column
//			 * mandatory? TODO add method support
//			 */
//			if (mappings.isSpecjProprietarySyntaxEnabled()) {
//				if (element.isAnnotationPresent(Id.class)
//						&& element.isAnnotationPresent(Column.class)) {
//					String columnName = element.getAnnotation(Column.class)
//							.name();
//					for (XProperty prop : declaringClass
//							.getDeclaredProperties(AccessType.FIELD.getType())) {
//						if (prop.isAnnotationPresent(JoinColumn.class)
//								&& prop.getAnnotation(JoinColumn.class).name()
//										.equals(columnName)
//								&& !prop.isAnnotationPresent(MapsId.class)) {
//							// create a PropertyData fpr the specJ property
//							// holding the mapping
//							PropertyData specJPropertyData = new PropertyInferredData(
//									declaringClass, // same dec
//									prop, // the actual @XToOne property
//									propertyAccessor, // TODO we should get the
//														// right accessor but
//														// the same as id would
//														// do
//									mappings.getReflectionManager());
//							mappings.addPropertyAnnotatedWithMapsIdSpecj(
//									entity, specJPropertyData,
//									element.toString());
//						}
//					}
//				}
//			}
//
//			if (element.isAnnotationPresent(ManyToOne.class)
//					|| element.isAnnotationPresent(OneToOne.class)) {
//				mappings.addToOneAndIdProperty(entity, propertyAnnotatedElement);
//			}
//			idPropertyCounter++;
//		} else {
//			annElts.add(propertyAnnotatedElement);
//		}
//		if (element.isAnnotationPresent(MapsId.class)) {
//			mappings.addPropertyAnnotatedWithMapsId(entity,
//					propertyAnnotatedElement);
//		}
//
//		return idPropertyCounter;
//	}
//
//	/*
//	 * Process annotation of a particular property
//	 */
//
//	private static void processElementAnnotations(
//			PropertyHolder propertyHolder, Nullability nullability,
//			PropertyData inferredData,
//			HashMap<String, IdGenerator> classGenerators,
//			EntityBinder entityBinder, boolean isIdentifierMapper,
//			boolean isComponentEmbedded, boolean inSecondPass,
//			Mappings mappings,
//			Map<XClass, InheritanceState> inheritanceStatePerClass)
//			throws MappingException {
//		/**
//		 * inSecondPass can only be used to apply right away the second pass of
//		 * a composite-element Because it's a value type, there is no
//		 * bidirectional association, hence second pass ordering does not matter
//		 */
//
//		log.trace("Processing annotations of {}.{}",
//				propertyHolder.getEntityName(), inferredData.getPropertyName());
//
//		final XProperty property = inferredData.getProperty();
//		if (property.isAnnotationPresent(Parent.class)) {
//			if (propertyHolder.isComponent()) {
//				propertyHolder.setParentProperty(property.getName());
//			} else {
//				throw new AnnotationException(
//						"@Parent cannot be applied outside an embeddable object: "
//								+ BinderHelper.getPath(propertyHolder,
//										inferredData));
//			}
//			return;
//		}
//
//		ColumnsBuilder columnsBuilder = new ColumnsBuilder(propertyHolder,
//				nullability, property, inferredData, entityBinder, mappings)
//				.extractMetadata();
//		Ejb3Column[] columns = columnsBuilder.getColumns();
//		Ejb3JoinColumn[] joinColumns = columnsBuilder.getJoinColumns();
//
//		final XClass returnedClass = inferredData.getClassOrElement();
//
//		// prepare PropertyBinder
//		PropertyBinder propertyBinder = new PropertyBinder();
//		propertyBinder.setName(inferredData.getPropertyName());
//		propertyBinder.setReturnedClassName(inferredData.getTypeName());
//		propertyBinder.setAccessType(inferredData.getDefaultAccess());
//		propertyBinder.setHolder(propertyHolder);
//		propertyBinder.setProperty(property);
//		propertyBinder.setReturnedClass(inferredData.getPropertyClass());
//		propertyBinder.setMappings(mappings);
//		if (isIdentifierMapper) {
//			propertyBinder.setInsertable(false);
//			propertyBinder.setUpdatable(false);
//		}
//		propertyBinder.setDeclaringClass(inferredData.getDeclaringClass());
//		propertyBinder.setEntityBinder(entityBinder);
//		propertyBinder.setInheritanceStatePerClass(inheritanceStatePerClass);
//
//		boolean isId = !entityBinder.isIgnoreIdAnnotations()
//				&& (property.isAnnotationPresent(Id.class) || property
//						.isAnnotationPresent(EmbeddedId.class));
//		propertyBinder.setId(isId);
//
//		if (property.isAnnotationPresent(Version.class)) {
//			if (isIdentifierMapper) {
//				throw new AnnotationException(
//						"@IdClass class should not have @Version property");
//			}
//			if (!(propertyHolder.getPersistentClass() instanceof RootClass)) {
//				throw new AnnotationException(
//						"Unable to define/override @Version on a subclass: "
//								+ propertyHolder.getEntityName());
//			}
//			if (!propertyHolder.isEntity()) {
//				throw new AnnotationException(
//						"Unable to define @Version on an embedded class: "
//								+ propertyHolder.getEntityName());
//			}
//			log.trace("{} is a version property",
//					inferredData.getPropertyName());
//			RootClass rootClass = (RootClass) propertyHolder
//					.getPersistentClass();
//			propertyBinder.setColumns(columns);
//			Property prop = propertyBinder.makePropertyValueAndBind();
//			setVersionInformation(property, propertyBinder);
//			rootClass.setVersion(prop);
//
//			// If version is on a mapped superclass, update the mapping
//			final org.hibernate.mapping.MappedSuperclass superclass = BinderHelper
//					.getMappedSuperclassOrNull(
//							inferredData.getDeclaringClass(),
//							inheritanceStatePerClass, mappings);
//			if (superclass != null) {
//				superclass.setDeclaredVersion(prop);
//			} else {
//				// we know the property is on the actual entity
//				rootClass.setDeclaredVersion(prop);
//			}
//
//			SimpleValue simpleValue = (SimpleValue) prop.getValue();
//			simpleValue.setNullValue("undefined");
//			rootClass.setOptimisticLockMode(Versioning.OPTIMISTIC_LOCK_VERSION);
//			log.trace("Version name: {}, unsavedValue: {}", rootClass
//					.getVersion().getName(), ((SimpleValue) rootClass
//					.getVersion().getValue()).getNullValue());
//		} else {
//			final boolean forcePersist = property
//					.isAnnotationPresent(MapsId.class)
//					|| property.isAnnotationPresent(Id.class);
//			if (property.isAnnotationPresent(ManyToOne.class)) {
//				ManyToOne ann = property.getAnnotation(ManyToOne.class);
//
//				// check validity
//				if (property.isAnnotationPresent(Column.class)
//						|| property.isAnnotationPresent(Columns.class)) {
//					throw new AnnotationException(
//							"@Column(s) not allowed on a @ManyToOne property: "
//									+ BinderHelper.getPath(propertyHolder,
//											inferredData));
//				}
//
//				Cascade hibernateCascade = property
//						.getAnnotation(Cascade.class);
//				NotFound notFound = property.getAnnotation(NotFound.class);
//				boolean ignoreNotFound = notFound != null
//						&& notFound.action().equals(NotFoundAction.IGNORE);
//				OnDelete onDeleteAnn = property.getAnnotation(OnDelete.class);
//				boolean onDeleteCascade = onDeleteAnn != null
//						&& OnDeleteAction.CASCADE.equals(onDeleteAnn.action());
//				JoinTable assocTable = propertyHolder.getJoinTable(property);
//				if (assocTable != null) {
//					Join join = propertyHolder.addJoin(assocTable, false);
//					for (Ejb3JoinColumn joinColumn : joinColumns) {
//						joinColumn.setSecondaryTableName(join.getTable()
//								.getName());
//					}
//				}
//				final boolean mandatory = !ann.optional() || forcePersist;
//				bindManyToOne(
//						getCascadeStrategy(ann.cascade(), hibernateCascade,
//								false, forcePersist), joinColumns, !mandatory,
//						ignoreNotFound, onDeleteCascade,
//						ToOneBinder.getTargetEntity(inferredData, mappings),
//						propertyHolder, inferredData, false,
//						isIdentifierMapper, inSecondPass, propertyBinder,
//						mappings);
//			} else if (property.isAnnotationPresent(OneToOne.class)) {
//				OneToOne ann = property.getAnnotation(OneToOne.class);
//
//				// check validity
//				if (property.isAnnotationPresent(Column.class)
//						|| property.isAnnotationPresent(Columns.class)) {
//					throw new AnnotationException(
//							"@Column(s) not allowed on a @OneToOne property: "
//									+ BinderHelper.getPath(propertyHolder,
//											inferredData));
//				}
//
//				// FIXME support a proper PKJCs
//				boolean trueOneToOne = property
//						.isAnnotationPresent(PrimaryKeyJoinColumn.class)
//						|| property
//								.isAnnotationPresent(PrimaryKeyJoinColumns.class);
//				Cascade hibernateCascade = property
//						.getAnnotation(Cascade.class);
//				NotFound notFound = property.getAnnotation(NotFound.class);
//				boolean ignoreNotFound = notFound != null
//						&& notFound.action().equals(NotFoundAction.IGNORE);
//				OnDelete onDeleteAnn = property.getAnnotation(OnDelete.class);
//				boolean onDeleteCascade = onDeleteAnn != null
//						&& OnDeleteAction.CASCADE.equals(onDeleteAnn.action());
//				JoinTable assocTable = propertyHolder.getJoinTable(property);
//				if (assocTable != null) {
//					Join join = propertyHolder.addJoin(assocTable, false);
//					for (Ejb3JoinColumn joinColumn : joinColumns) {
//						joinColumn.setSecondaryTableName(join.getTable()
//								.getName());
//					}
//				}
//				// MapsId means the columns belong to the pk => not null
//				// @PKJC must be constrained
//				final boolean mandatory = !ann.optional() || forcePersist
//						|| trueOneToOne;
//				bindOneToOne(
//						getCascadeStrategy(ann.cascade(), hibernateCascade,
//								ann.orphanRemoval(), forcePersist),
//						joinColumns, !mandatory, getFetchMode(ann.fetch()),
//						ignoreNotFound, onDeleteCascade,
//						ToOneBinder.getTargetEntity(inferredData, mappings),
//						propertyHolder, inferredData, ann.mappedBy(),
//						trueOneToOne, isIdentifierMapper, inSecondPass,
//						propertyBinder, mappings);
//			} else if (property
//					.isAnnotationPresent(org.hibernate.annotations.Any.class)) {
//
//				// check validity
//				if (property.isAnnotationPresent(Column.class)
//						|| property.isAnnotationPresent(Columns.class)) {
//					throw new AnnotationException(
//							"@Column(s) not allowed on a @Any property: "
//									+ BinderHelper.getPath(propertyHolder,
//											inferredData));
//				}
//
//				Cascade hibernateCascade = property
//						.getAnnotation(Cascade.class);
//				OnDelete onDeleteAnn = property.getAnnotation(OnDelete.class);
//				boolean onDeleteCascade = onDeleteAnn != null
//						&& OnDeleteAction.CASCADE.equals(onDeleteAnn.action());
//				JoinTable assocTable = propertyHolder.getJoinTable(property);
//				if (assocTable != null) {
//					Join join = propertyHolder.addJoin(assocTable, false);
//					for (Ejb3JoinColumn joinColumn : joinColumns) {
//						joinColumn.setSecondaryTableName(join.getTable()
//								.getName());
//					}
//				}
//				bindAny(getCascadeStrategy(null, hibernateCascade, false,
//						forcePersist),
//						// @Any has not cascade attribute
//						joinColumns, onDeleteCascade, nullability,
//						propertyHolder, inferredData, entityBinder,
//						isIdentifierMapper, mappings);
//			} else if (property.isAnnotationPresent(OneToMany.class)
//					|| property.isAnnotationPresent(ManyToMany.class)
//					|| property.isAnnotationPresent(CollectionOfElements.class) // legacy
//																				// Hibernate
//					|| property.isAnnotationPresent(ElementCollection.class)
//					|| property.isAnnotationPresent(ManyToAny.class)) {
//				OneToMany oneToManyAnn = property
//						.getAnnotation(OneToMany.class);
//				ManyToMany manyToManyAnn = property
//						.getAnnotation(ManyToMany.class);
//				ElementCollection elementCollectionAnn = property
//						.getAnnotation(ElementCollection.class);
//				CollectionOfElements collectionOfElementsAnn = property
//						.getAnnotation(CollectionOfElements.class); // legacy
//																	// hibernate
//
//				final IndexColumn indexColumn;
//
//				if (property.isAnnotationPresent(OrderColumn.class)) {
//					indexColumn = IndexColumn.buildColumnFromAnnotation(
//							property.getAnnotation(OrderColumn.class),
//							propertyHolder, inferredData,
//							entityBinder.getSecondaryTables(), mappings);
//				} else {
//					// if @IndexColumn is not there, the generated IndexColumn
//					// is an implicit column and not used.
//					// so we can leave the legacy processing as the default
//					indexColumn = IndexColumn
//							.buildColumnFromAnnotation(
//									property.getAnnotation(org.hibernate.annotations.IndexColumn.class),
//									propertyHolder, inferredData, mappings);
//				}
//				CollectionBinder collectionBinder = CollectionBinder
//						.getCollectionBinder(
//								propertyHolder.getEntityName(),
//								property,
//								!indexColumn.isImplicit(),
//								property.isAnnotationPresent(CollectionOfElements.class)
//										|| property
//												.isAnnotationPresent(org.hibernate.annotations.MapKey.class)
//										|| property
//												.isAnnotationPresent(MapKeyType.class)
//
//						// || property.isAnnotationPresent( ManyToAny.class )
//						);
//				collectionBinder.setIndexColumn(indexColumn);
//				collectionBinder
//						.setMapKey(property.getAnnotation(MapKey.class));
//				collectionBinder
//						.setPropertyName(inferredData.getPropertyName());
//				BatchSize batchAnn = property.getAnnotation(BatchSize.class);
//				collectionBinder.setBatchSize(batchAnn);
//				javax.persistence.OrderBy ejb3OrderByAnn = property
//						.getAnnotation(javax.persistence.OrderBy.class);
//				OrderBy orderByAnn = property.getAnnotation(OrderBy.class);
//				collectionBinder.setEjb3OrderBy(ejb3OrderByAnn);
//				collectionBinder.setSqlOrderBy(orderByAnn);
//				Sort sortAnn = property.getAnnotation(Sort.class);
//				collectionBinder.setSort(sortAnn);
//				Cache cachAnn = property.getAnnotation(Cache.class);
//				collectionBinder.setCache(cachAnn);
//				collectionBinder.setPropertyHolder(propertyHolder);
//				Cascade hibernateCascade = property
//						.getAnnotation(Cascade.class);
//				NotFound notFound = property.getAnnotation(NotFound.class);
//				boolean ignoreNotFound = notFound != null
//						&& notFound.action().equals(NotFoundAction.IGNORE);
//				collectionBinder.setIgnoreNotFound(ignoreNotFound);
//				collectionBinder.setCollectionType(inferredData.getProperty()
//						.getElementClass());
//				collectionBinder.setMappings(mappings);
//				collectionBinder.setAccessType(inferredData.getDefaultAccess());
//
//				Ejb3Column[] elementColumns;
//				// do not use "element" if you are a JPA 2 @ElementCollection
//				// only for legacy Hibernate mappings
//				boolean isJPA2ForValueMapping = property
//						.isAnnotationPresent(ElementCollection.class);
//				PropertyData virtualProperty = isJPA2ForValueMapping ? inferredData
//						: new WrappedInferredData(inferredData, "element");
//				if (property.isAnnotationPresent(Column.class)
//						|| property.isAnnotationPresent(Formula.class)) {
//					Column ann = property.getAnnotation(Column.class);
//					Formula formulaAnn = property.getAnnotation(Formula.class);
//					elementColumns = Ejb3Column.buildColumnFromAnnotation(
//							new Column[] { ann }, formulaAnn, nullability,
//							propertyHolder, virtualProperty,
//							entityBinder.getSecondaryTables(), mappings);
//				} else if (property.isAnnotationPresent(Columns.class)) {
//					Columns anns = property.getAnnotation(Columns.class);
//					elementColumns = Ejb3Column.buildColumnFromAnnotation(
//							anns.columns(), null, nullability, propertyHolder,
//							virtualProperty, entityBinder.getSecondaryTables(),
//							mappings);
//				} else {
//					elementColumns = Ejb3Column.buildColumnFromAnnotation(null,
//							null, nullability, propertyHolder, virtualProperty,
//							entityBinder.getSecondaryTables(), mappings);
//				}
//				{
//					Column[] keyColumns = null;
//					// JPA 2 has priority and has different default column
//					// values, differenciate legacy from JPA 2
//					Boolean isJPA2 = null;
//					if (property.isAnnotationPresent(MapKeyColumn.class)) {
//						isJPA2 = Boolean.TRUE;
//						keyColumns = new Column[] { new MapKeyColumnDelegator(
//								property.getAnnotation(MapKeyColumn.class)) };
//					} else if (property
//							.isAnnotationPresent(org.hibernate.annotations.MapKey.class)) {
//						if (isJPA2 == null) {
//							isJPA2 = Boolean.FALSE;
//						}
//						keyColumns = property.getAnnotation(
//								org.hibernate.annotations.MapKey.class)
//								.columns();
//					}
//
//					// not explicitly legacy
//					if (isJPA2 == null) {
//						isJPA2 = Boolean.TRUE;
//					}
//
//					// nullify empty array
//					keyColumns = keyColumns != null && keyColumns.length > 0 ? keyColumns
//							: null;
//
//					// "mapkey" is the legacy column name of the key column pre
//					// JPA 2
//					PropertyData mapKeyVirtualProperty = new WrappedInferredData(
//							inferredData, "mapkey");
//					Ejb3Column[] mapColumns = Ejb3Column
//							.buildColumnFromAnnotation(keyColumns, null,
//									Nullability.FORCED_NOT_NULL,
//									propertyHolder, isJPA2 ? inferredData
//											: mapKeyVirtualProperty,
//									isJPA2 ? "_KEY" : null, entityBinder
//											.getSecondaryTables(), mappings);
//					collectionBinder.setMapKeyColumns(mapColumns);
//				}
//				{
//					JoinColumn[] joinKeyColumns = null;
//					// JPA 2 has priority and has different default column
//					// values, differenciate legacy from JPA 2
//					Boolean isJPA2 = null;
//					if (property.isAnnotationPresent(MapKeyJoinColumns.class)) {
//						isJPA2 = Boolean.TRUE;
//						final MapKeyJoinColumn[] mapKeyJoinColumns = property
//								.getAnnotation(MapKeyJoinColumns.class).value();
//						joinKeyColumns = new JoinColumn[mapKeyJoinColumns.length];
//						int index = 0;
//						for (MapKeyJoinColumn joinColumn : mapKeyJoinColumns) {
//							joinKeyColumns[index] = new MapKeyJoinColumnDelegator(
//									joinColumn);
//							index++;
//						}
//						if (joinKeyColumns != null) {
//							throw new AnnotationException(
//									"@MapKeyJoinColumn and @MapKeyJoinColumns used on the same property: "
//											+ BinderHelper.getPath(
//													propertyHolder,
//													inferredData));
//						}
//					} else if (property
//							.isAnnotationPresent(MapKeyJoinColumn.class)) {
//						isJPA2 = Boolean.TRUE;
//						joinKeyColumns = new JoinColumn[] { new MapKeyJoinColumnDelegator(
//								property.getAnnotation(MapKeyJoinColumn.class)) };
//					} else if (property
//							.isAnnotationPresent(org.hibernate.annotations.MapKeyManyToMany.class)) {
//						if (isJPA2 == null) {
//							isJPA2 = Boolean.FALSE;
//						}
//						joinKeyColumns = property
//								.getAnnotation(
//										org.hibernate.annotations.MapKeyManyToMany.class)
//								.joinColumns();
//					}
//
//					// not explicitly legacy
//					if (isJPA2 == null) {
//						isJPA2 = Boolean.TRUE;
//					}
//
//					PropertyData mapKeyVirtualProperty = new WrappedInferredData(
//							inferredData, "mapkey");
//					Ejb3JoinColumn[] mapJoinColumns = Ejb3JoinColumn
//							.buildJoinColumnsWithDefaultColumnSuffix(
//									joinKeyColumns,
//									null,
//									entityBinder.getSecondaryTables(),
//									propertyHolder,
//									isJPA2 ? inferredData.getPropertyName()
//											: mapKeyVirtualProperty
//													.getPropertyName(),
//									isJPA2 ? "_KEY" : null, mappings);
//					collectionBinder.setMapKeyManyToManyColumns(mapJoinColumns);
//				}
//
//				// potential element
//				collectionBinder.setEmbedded(property
//						.isAnnotationPresent(Embedded.class));
//				collectionBinder.setElementColumns(elementColumns);
//				collectionBinder.setProperty(property);
//
//				// TODO enhance exception with @ManyToAny and
//				// @CollectionOfElements
//				if (oneToManyAnn != null && manyToManyAnn != null) {
//					throw new AnnotationException(
//							"@OneToMany and @ManyToMany on the same property is not allowed: "
//									+ propertyHolder.getEntityName() + "."
//									+ inferredData.getPropertyName());
//				}
//				String mappedBy = null;
//				if (oneToManyAnn != null) {
//					for (Ejb3JoinColumn column : joinColumns) {
//						if (column.isSecondary()) {
//							throw new NotYetImplementedException(
//									"Collections having FK in secondary table");
//						}
//					}
//					collectionBinder.setFkJoinColumns(joinColumns);
//					mappedBy = oneToManyAnn.mappedBy();
//					collectionBinder.setTargetEntity(mappings
//							.getReflectionManager().toXClass(
//									oneToManyAnn.targetEntity()));
//					collectionBinder.setCascadeStrategy(getCascadeStrategy(
//							oneToManyAnn.cascade(), hibernateCascade,
//							oneToManyAnn.orphanRemoval(), false));
//					collectionBinder.setOneToMany(true);
//				} else if (elementCollectionAnn != null
//						|| collectionOfElementsAnn != null // Hibernate legacy
//				) {
//					for (Ejb3JoinColumn column : joinColumns) {
//						if (column.isSecondary()) {
//							throw new NotYetImplementedException(
//									"Collections having FK in secondary table");
//						}
//					}
//					collectionBinder.setFkJoinColumns(joinColumns);
//					mappedBy = "";
//					final Class<?> targetElement = elementCollectionAnn != null ? elementCollectionAnn
//							.targetClass() : collectionOfElementsAnn
//							.targetElement();
//					collectionBinder.setTargetEntity(mappings
//							.getReflectionManager().toXClass(targetElement));
//					// collectionBinder.setCascadeStrategy( getCascadeStrategy(
//					// embeddedCollectionAnn.cascade(), hibernateCascade ) );
//					collectionBinder.setOneToMany(true);
//				} else if (manyToManyAnn != null) {
//					mappedBy = manyToManyAnn.mappedBy();
//					collectionBinder.setTargetEntity(mappings
//							.getReflectionManager().toXClass(
//									manyToManyAnn.targetEntity()));
//					collectionBinder.setCascadeStrategy(getCascadeStrategy(
//							manyToManyAnn.cascade(), hibernateCascade, false,
//							false));
//					collectionBinder.setOneToMany(false);
//				} else if (property.isAnnotationPresent(ManyToAny.class)) {
//					mappedBy = "";
//					collectionBinder.setTargetEntity(mappings
//							.getReflectionManager().toXClass(void.class));
//					collectionBinder.setCascadeStrategy(getCascadeStrategy(
//							null, hibernateCascade, false, false));
//					collectionBinder.setOneToMany(false);
//				}
//				collectionBinder.setMappedBy(mappedBy);
//
//				bindJoinedTableAssociation(property, mappings, entityBinder,
//						collectionBinder, propertyHolder, inferredData,
//						mappedBy);
//
//				OnDelete onDeleteAnn = property.getAnnotation(OnDelete.class);
//				boolean onDeleteCascade = onDeleteAnn != null
//						&& OnDeleteAction.CASCADE.equals(onDeleteAnn.action());
//				collectionBinder.setCascadeDeleteEnabled(onDeleteCascade);
//				if (isIdentifierMapper) {
//					collectionBinder.setInsertable(false);
//					collectionBinder.setUpdatable(false);
//				}
//				if (property.isAnnotationPresent(CollectionId.class)) { // do
//																		// not
//																		// compute
//																		// the
//																		// generators
//																		// unless
//																		// necessary
//					HashMap<String, IdGenerator> localGenerators = (HashMap<String, IdGenerator>) classGenerators
//							.clone();
//					localGenerators.putAll(buildLocalGenerators(property,
//							mappings));
//					collectionBinder.setLocalGenerators(localGenerators);
//
//				}
//				collectionBinder
//						.setInheritanceStatePerClass(inheritanceStatePerClass);
//				collectionBinder.setDeclaringClass(inferredData
//						.getDeclaringClass());
//				collectionBinder.bind();
//
//			}
//			// Either a regular property or a basic @Id or @EmbeddedId while not
//			// ignoring id annotations
//			else if (!isId || !entityBinder.isIgnoreIdAnnotations()) {
//				// define whether the type is a component or not
//
//				boolean isComponent = false;
//
//				// Overrides from @MapsId if needed
//				boolean isOverridden = false;
//				if (isId || propertyHolder.isOrWithinEmbeddedId()
//						|| propertyHolder.isInIdClass()) {
//					// the associated entity could be using an @IdClass making
//					// the overridden property a component
//					final PropertyData overridingProperty = BinderHelper
//							.getPropertyOverriddenByMapperOrMapsId(isId,
//									propertyHolder, property.getName(),
//									mappings);
//					if (overridingProperty != null) {
//						isOverridden = true;
//						final InheritanceState state = inheritanceStatePerClass
//								.get(overridingProperty.getClassOrElement());
//						if (state != null) {
//							isComponent = isComponent
//									|| state.hasIdClassOrEmbeddedId();
//						}
//						// Get the new column
//						columns = columnsBuilder
//								.overrideColumnFromMapperOrMapsIdProperty(isId);
//					}
//				}
//
//				isComponent = isComponent
//						|| property.isAnnotationPresent(Embedded.class)
//						|| property.isAnnotationPresent(EmbeddedId.class)
//						|| returnedClass.isAnnotationPresent(Embeddable.class);
//
//				if (isComponent) {
//					String referencedEntityName = null;
//					if (isOverridden) {
//						final PropertyData mapsIdProperty = BinderHelper
//								.getPropertyOverriddenByMapperOrMapsId(isId,
//										propertyHolder, property.getName(),
//										mappings);
//						referencedEntityName = mapsIdProperty
//								.getClassOrElementName();
//					}
//					AccessType propertyAccessor = entityBinder
//							.getPropertyAccessor(property);
//					propertyBinder = bindComponent(inferredData,
//							propertyHolder, propertyAccessor, entityBinder,
//							isIdentifierMapper, mappings, isComponentEmbedded,
//							isId, inheritanceStatePerClass,
//							referencedEntityName,
//							isOverridden ? (Ejb3JoinColumn[]) columns : null);
//				} else {
//					// provide the basic property mapping
//					boolean optional = true;
//					boolean lazy = false;
//					if (property.isAnnotationPresent(Basic.class)) {
//						Basic ann = property.getAnnotation(Basic.class);
//						optional = ann.optional();
//						lazy = ann.fetch() == FetchType.LAZY;
//					}
//					// implicit type will check basic types and Serializable
//					// classes
//					if (isId
//							|| (!optional && nullability != Nullability.FORCED_NULL)) {
//						// force columns to not null
//						for (Ejb3Column col : columns) {
//							col.forceNotNull();
//						}
//					}
//
//					propertyBinder.setLazy(lazy);
//					propertyBinder.setColumns(columns);
//					if (isOverridden) {
//						final PropertyData mapsIdProperty = BinderHelper
//								.getPropertyOverriddenByMapperOrMapsId(isId,
//										propertyHolder, property.getName(),
//										mappings);
//						propertyBinder.setReferencedEntityName(mapsIdProperty
//								.getClassOrElementName());
//					}
//
//					propertyBinder.makePropertyValueAndBind();
//
//				}
//				if (isOverridden) {
//					final PropertyData mapsIdProperty = BinderHelper
//							.getPropertyOverriddenByMapperOrMapsId(isId,
//									propertyHolder, property.getName(),
//									mappings);
//					Map<String, IdGenerator> localGenerators = (HashMap<String, IdGenerator>) classGenerators
//							.clone();
//					final IdGenerator foreignGenerator = new IdGenerator();
//					foreignGenerator.setIdentifierGeneratorStrategy("assigned");
//					foreignGenerator
//							.setName("Hibernate-local--foreign generator");
//					foreignGenerator.setIdentifierGeneratorStrategy("foreign");
//					foreignGenerator.addParam("property",
//							mapsIdProperty.getPropertyName());
//					localGenerators.put(foreignGenerator.getName(),
//							foreignGenerator);
//
//					BinderHelper.makeIdGenerator(
//							(SimpleValue) propertyBinder.getValue(),
//							foreignGenerator.getIdentifierGeneratorStrategy(),
//							foreignGenerator.getName(), mappings,
//							localGenerators);
//				}
//				if (isId) {
//					// components and regular basic types create SimpleValue
//					// objects
//					final SimpleValue value = (SimpleValue) propertyBinder
//							.getValue();
//					if (!isOverridden) {
//						processId(propertyHolder, inferredData, value,
//								classGenerators, isIdentifierMapper, mappings);
//					}
//				}
//			}
//		}
//		// init index
//		// process indexes after everything: in second pass, many to one has to
//		// be done before indexes
//		Index index = property.getAnnotation(Index.class);
//		if (index != null) {
//			if (joinColumns != null) {
//
//				for (Ejb3Column column : joinColumns) {
//					column.addIndex(index, inSecondPass);
//				}
//			} else {
//				if (columns != null) {
//					for (Ejb3Column column : columns) {
//						column.addIndex(index, inSecondPass);
//					}
//				}
//			}
//		}
//
//		NaturalId naturalIdAnn = property.getAnnotation(NaturalId.class);
//		if (naturalIdAnn != null) {
//			if (joinColumns != null) {
//				for (Ejb3Column column : joinColumns) {
//					column.addUniqueKey("_UniqueKey", inSecondPass);
//				}
//			} else {
//				for (Ejb3Column column : columns) {
//					column.addUniqueKey("_UniqueKey", inSecondPass);
//				}
//			}
//		}
//	}
//
//	private static void setVersionInformation(XProperty property,
//			PropertyBinder propertyBinder) {
//		propertyBinder.getSimpleValueBinder().setVersion(true);
//		if (property.isAnnotationPresent(Source.class)) {
//			Source source = property.getAnnotation(Source.class);
//			propertyBinder.getSimpleValueBinder().setTimestampVersionType(
//					source.value().typeName());
//		}
//	}
//
//	private static void processId(PropertyHolder propertyHolder,
//			PropertyData inferredData, SimpleValue idValue,
//			HashMap<String, IdGenerator> classGenerators,
//			boolean isIdentifierMapper, Mappings mappings) {
//		if (isIdentifierMapper) {
//			throw new AnnotationException(
//					"@IdClass class should not have @Id nor @EmbeddedId properties: "
//							+ BinderHelper
//									.getPath(propertyHolder, inferredData));
//		}
//		XClass returnedClass = inferredData.getClassOrElement();
//		XProperty property = inferredData.getProperty();
//		// clone classGenerator and override with local values
//		HashMap<String, IdGenerator> localGenerators = (HashMap<String, IdGenerator>) classGenerators
//				.clone();
//		localGenerators.putAll(buildLocalGenerators(property, mappings));
//
//		// manage composite related metadata
//		// guess if its a component and find id data access (property, field
//		// etc)
//		final boolean isComponent = returnedClass
//				.isAnnotationPresent(Embeddable.class)
//				|| property.isAnnotationPresent(EmbeddedId.class);
//
//		GeneratedValue generatedValue = property
//				.getAnnotation(GeneratedValue.class);
//		String generatorType = generatedValue != null ? generatorType(
//				generatedValue.strategy(), mappings) : "assigned";
//		String generatorName = generatedValue != null ? generatedValue
//				.generator() : BinderHelper.ANNOTATION_STRING_DEFAULT;
//		if (isComponent) {
//			generatorType = "assigned";
//		} // a component must not have any generator
//		BinderHelper.makeIdGenerator(idValue, generatorType, generatorName,
//				mappings, localGenerators);
//
//		log.trace("Bind {} on {}", (isComponent ? "@EmbeddedId" : "@Id"),
//				inferredData.getPropertyName());
//	}
//
//	// TODO move that to collection binder?
//
//	private static void bindJoinedTableAssociation(XProperty property,
//			Mappings mappings, EntityBinder entityBinder,
//			CollectionBinder collectionBinder, PropertyHolder propertyHolder,
//			PropertyData inferredData, String mappedBy) {
//		TableBinder associationTableBinder = new TableBinder();
//		JoinColumn[] annJoins;
//		JoinColumn[] annInverseJoins;
//		JoinTable assocTable = propertyHolder.getJoinTable(property);
//		CollectionTable collectionTable = property
//				.getAnnotation(CollectionTable.class);
//
//		if (assocTable != null || collectionTable != null) {
//
//			final String catalog;
//			final String schema;
//			final String tableName;
//			final UniqueConstraint[] uniqueConstraints;
//			final JoinColumn[] joins;
//			final JoinColumn[] inverseJoins;
//
//			// JPA 2 has priority
//			if (collectionTable != null) {
//				catalog = collectionTable.catalog();
//				schema = collectionTable.schema();
//				tableName = collectionTable.name();
//				uniqueConstraints = collectionTable.uniqueConstraints();
//				joins = collectionTable.joinColumns();
//				inverseJoins = null;
//			} else {
//				catalog = assocTable.catalog();
//				schema = assocTable.schema();
//				tableName = assocTable.name();
//				uniqueConstraints = assocTable.uniqueConstraints();
//				joins = assocTable.joinColumns();
//				inverseJoins = assocTable.inverseJoinColumns();
//			}
//
//			collectionBinder.setExplicitAssociationTable(true);
//
//			if (!BinderHelper.isEmptyAnnotationValue(schema)) {
//				associationTableBinder.setSchema(schema);
//			}
//			if (!BinderHelper.isEmptyAnnotationValue(catalog)) {
//				associationTableBinder.setCatalog(catalog);
//			}
//			if (!BinderHelper.isEmptyAnnotationValue(tableName)) {
//				associationTableBinder.setName(tableName);
//			}
//			associationTableBinder.setUniqueConstraints(uniqueConstraints);
//
//			// set check constaint in the second pass
//			annJoins = joins.length == 0 ? null : joins;
//			annInverseJoins = inverseJoins == null || inverseJoins.length == 0 ? null
//					: inverseJoins;
//		} else {
//			annJoins = null;
//			annInverseJoins = null;
//		}
//		Ejb3JoinColumn[] joinColumns = Ejb3JoinColumn
//				.buildJoinTableJoinColumns(annJoins,
//						entityBinder.getSecondaryTables(), propertyHolder,
//						inferredData.getPropertyName(), mappedBy, mappings);
//		Ejb3JoinColumn[] inverseJoinColumns = Ejb3JoinColumn
//				.buildJoinTableJoinColumns(annInverseJoins,
//						entityBinder.getSecondaryTables(), propertyHolder,
//						inferredData.getPropertyName(), mappedBy, mappings);
//		associationTableBinder.setMappings(mappings);
//		collectionBinder.setTableBinder(associationTableBinder);
//		collectionBinder.setJoinColumns(joinColumns);
//		collectionBinder.setInverseJoinColumns(inverseJoinColumns);
//	}
//
//	private static PropertyBinder bindComponent(PropertyData inferredData,
//			PropertyHolder propertyHolder, AccessType propertyAccessor,
//			EntityBinder entityBinder, boolean isIdentifierMapper,
//			Mappings mappings, boolean isComponentEmbedded,
//			boolean isId, // is a identifier
//			Map<XClass, InheritanceState> inheritanceStatePerClass,
//			String referencedEntityName, // is a component who is overridden by
//											// a @MapsId
//			Ejb3JoinColumn[] columns) {
//		Component comp;
//		if (referencedEntityName != null) {
//			comp = createComponent(propertyHolder, inferredData,
//					isComponentEmbedded, isIdentifierMapper, mappings);
//			SecondPass sp = new CopyIdentifierComponentSecondPass(comp,
//					referencedEntityName, columns, mappings);
//			mappings.addSecondPass(sp);
//		} else {
//			comp = fillComponent(propertyHolder, inferredData,
//					propertyAccessor, !isId, entityBinder, isComponentEmbedded,
//					isIdentifierMapper, false, mappings,
//					inheritanceStatePerClass);
//		}
//		if (isId) {
//			comp.setKey(true);
//			if (propertyHolder.getPersistentClass().getIdentifier() != null) {
//				throw new AnnotationException(
//						comp.getComponentClassName()
//								+ " must not have @Id properties when used as an @EmbeddedId: "
//								+ BinderHelper.getPath(propertyHolder,
//										inferredData));
//			}
//			if (referencedEntityName == null && comp.getPropertySpan() == 0) {
//				throw new AnnotationException(comp.getComponentClassName()
//						+ " has no persistent id property: "
//						+ BinderHelper.getPath(propertyHolder, inferredData));
//			}
//		}
//		XProperty property = inferredData.getProperty();
//		setupComponentTuplizer(property, comp);
//		PropertyBinder binder = new PropertyBinder();
//		binder.setName(inferredData.getPropertyName());
//		binder.setValue(comp);
//		binder.setProperty(inferredData.getProperty());
//		binder.setAccessType(inferredData.getDefaultAccess());
//		binder.setEmbedded(isComponentEmbedded);
//		binder.setHolder(propertyHolder);
//		binder.setId(isId);
//		binder.setEntityBinder(entityBinder);
//		binder.setInheritanceStatePerClass(inheritanceStatePerClass);
//		binder.setMappings(mappings);
//		binder.makePropertyAndBind();
//		return binder;
//	}
//
//	public static Component fillComponent(PropertyHolder propertyHolder,
//			PropertyData inferredData, AccessType propertyAccessor,
//			boolean isNullable, EntityBinder entityBinder,
//			boolean isComponentEmbedded, boolean isIdentifierMapper,
//			boolean inSecondPass, Mappings mappings,
//			Map<XClass, InheritanceState> inheritanceStatePerClass) {
//		return fillComponent(propertyHolder, inferredData, null,
//				propertyAccessor, isNullable, entityBinder,
//				isComponentEmbedded, isIdentifierMapper, inSecondPass,
//				mappings, inheritanceStatePerClass);
//	}
//
//	public static Component fillComponent(
//			PropertyHolder propertyHolder,
//			PropertyData inferredData,
//			PropertyData baseInferredData, // base inferred data correspond to
//											// the entity reproducing
//											// inferredData's properties (ie
//											// IdClass)
//			AccessType propertyAccessor, boolean isNullable,
//			EntityBinder entityBinder, boolean isComponentEmbedded,
//			boolean isIdentifierMapper, boolean inSecondPass,
//			Mappings mappings,
//			Map<XClass, InheritanceState> inheritanceStatePerClass) {
//		/**
//		 * inSecondPass can only be used to apply right away the second pass of
//		 * a composite-element Because it's a value type, there is no
//		 * bidirectional association, hence second pass ordering does not matter
//		 */
//		Component comp = createComponent(propertyHolder, inferredData,
//				isComponentEmbedded, isIdentifierMapper, mappings);
//		String subpath = BinderHelper.getPath(propertyHolder, inferredData);
//		log.trace("Binding component with path: {}", subpath);
//		PropertyHolder subHolder = PropertyHolderBuilder.buildPropertyHolder(
//				comp, subpath, inferredData, propertyHolder, mappings);
//
//		final XClass xClassProcessed = inferredData.getPropertyClass();
//		List<PropertyData> classElements = new ArrayList<PropertyData>();
//		XClass returnedClassOrElement = inferredData.getClassOrElement();
//
//		List<PropertyData> baseClassElements = null;
//		Map<String, PropertyData> orderedBaseClassElements = new HashMap<String, PropertyData>();
//		XClass baseReturnedClassOrElement;
//		if (baseInferredData != null) {
//			baseClassElements = new ArrayList<PropertyData>();
//			baseReturnedClassOrElement = baseInferredData.getClassOrElement();
//			bindTypeDefs(baseReturnedClassOrElement, mappings);
//			PropertyContainer propContainer = new PropertyContainer(
//					baseReturnedClassOrElement, xClassProcessed);
//			addElementsOfClass(baseClassElements, propertyAccessor,
//					propContainer, mappings);
//			for (PropertyData element : baseClassElements) {
//				orderedBaseClassElements
//						.put(element.getPropertyName(), element);
//			}
//		}
//
//		// embeddable elements can have type defs
//		bindTypeDefs(returnedClassOrElement, mappings);
//		PropertyContainer propContainer = new PropertyContainer(
//				returnedClassOrElement, xClassProcessed);
//		addElementsOfClass(classElements, propertyAccessor, propContainer,
//				mappings);
//
//		// add elements of the embeddable superclass
//		XClass superClass = xClassProcessed.getSuperclass();
//		while (superClass != null
//				&& superClass.isAnnotationPresent(MappedSuperclass.class)) {
//			// FIXME: proper support of typevariables incl var resolved at upper
//			// levels
//			propContainer = new PropertyContainer(superClass, xClassProcessed);
//			addElementsOfClass(classElements, propertyAccessor, propContainer,
//					mappings);
//			superClass = superClass.getSuperclass();
//		}
//		if (baseClassElements != null) {
//			// useful to avoid breaking pre JPA 2 mappings
//			if (!hasAnnotationsOnIdClass(xClassProcessed)) {
//				for (int i = 0; i < classElements.size(); i++) {
//					final PropertyData idClassPropertyData = classElements
//							.get(i);
//					final PropertyData entityPropertyData = orderedBaseClassElements
//							.get(idClassPropertyData.getPropertyName());
//					if (propertyHolder.isInIdClass()) {
//						if (entityPropertyData == null) {
//							throw new AnnotationException(
//									"Property of @IdClass not found in entity "
//											+ baseInferredData
//													.getPropertyClass()
//													.getName()
//											+ ": "
//											+ idClassPropertyData
//													.getPropertyName());
//						}
//						final boolean hasXToOneAnnotation = entityPropertyData
//								.getProperty().isAnnotationPresent(
//										ManyToOne.class)
//								|| entityPropertyData.getProperty()
//										.isAnnotationPresent(OneToOne.class);
//						final boolean isOfDifferentType = !entityPropertyData
//								.getClassOrElement()
//								.equals(idClassPropertyData.getClassOrElement());
//						if (hasXToOneAnnotation && isOfDifferentType) {
//							// don't replace here as we need to use the actual
//							// original return type
//							// the annotation overriding will be dealt with by a
//							// mechanism similar to @MapsId
//						} else {
//							classElements.set(i, entityPropertyData); // this
//																		// works
//																		// since
//																		// they
//																		// are
//																		// in
//																		// the
//																		// same
//																		// order
//						}
//					} else {
//						classElements.set(i, entityPropertyData); // this works
//																	// since
//																	// they are
//																	// in the
//																	// same
//																	// order
//					}
//				}
//			}
//		}
//		for (PropertyData propertyAnnotatedElement : classElements) {
//			processElementAnnotations(subHolder,
//					isNullable ? Nullability.NO_CONSTRAINT
//							: Nullability.FORCED_NOT_NULL,
//					propertyAnnotatedElement,
//					new HashMap<String, IdGenerator>(), entityBinder,
//					isIdentifierMapper, isComponentEmbedded, inSecondPass,
//					mappings, inheritanceStatePerClass);
//
//			XProperty property = propertyAnnotatedElement.getProperty();
//			if (property.isAnnotationPresent(GeneratedValue.class)
//					&& property.isAnnotationPresent(Id.class)) {
//				// clone classGenerator and override with local values
//				Map<String, IdGenerator> localGenerators = new HashMap<String, IdGenerator>();
//				localGenerators
//						.putAll(buildLocalGenerators(property, mappings));
//
//				GeneratedValue generatedValue = property
//						.getAnnotation(GeneratedValue.class);
//				String generatorType = generatedValue != null ? generatorType(
//						generatedValue.strategy(), mappings) : "assigned";
//				String generator = generatedValue != null ? generatedValue
//						.generator() : BinderHelper.ANNOTATION_STRING_DEFAULT;
//
//				BinderHelper.makeIdGenerator(
//						(SimpleValue) comp.getProperty(property.getName())
//								.getValue(), generatorType, generator,
//						mappings, localGenerators);
//			}
//
//		}
//		return comp;
//	}
//
//	public static Component createComponent(PropertyHolder propertyHolder,
//			PropertyData inferredData, boolean isComponentEmbedded,
//			boolean isIdentifierMapper, Mappings mappings) {
//		Component comp = new Component(mappings,
//				propertyHolder.getPersistentClass());
//		comp.setEmbedded(isComponentEmbedded);
//		// yuk
//		comp.setTable(propertyHolder.getTable());
//		// FIXME shouldn't identifier mapper use getClassOrElementName? Need to
//		// be checked.
//		if (isIdentifierMapper
//				|| (isComponentEmbedded && inferredData.getPropertyName() == null)) {
//			comp.setComponentClassName(comp.getOwner().getClassName());
//		} else {
//			comp.setComponentClassName(inferredData.getClassOrElementName());
//		}
//		comp.setNodeName(inferredData.getPropertyName());
//		return comp;
//	}
//
//	private static void bindIdClass(String generatorType, String generatorName,
//			PropertyData inferredData, PropertyData baseInferredData,
//			Ejb3Column[] columns, PropertyHolder propertyHolder,
//			boolean isComposite, AccessType propertyAccessor,
//			EntityBinder entityBinder, boolean isEmbedded,
//			boolean isIdentifierMapper, Mappings mappings,
//			Map<XClass, InheritanceState> inheritanceStatePerClass) {
//
//		/*
//		 * Fill simple value and property since and Id is a property
//		 */
//		PersistentClass persistentClass = propertyHolder.getPersistentClass();
//		if (!(persistentClass instanceof RootClass)) {
//			throw new AnnotationException(
//					"Unable to define/override @Id(s) on a subclass: "
//							+ propertyHolder.getEntityName());
//		}
//		RootClass rootClass = (RootClass) persistentClass;
//		String persistentClassName = rootClass.getClassName();
//		SimpleValue id;
//		final String propertyName = inferredData.getPropertyName();
//		HashMap<String, IdGenerator> localGenerators = new HashMap<String, IdGenerator>();
//		if (isComposite) {
//			id = fillComponent(propertyHolder, inferredData, baseInferredData,
//					propertyAccessor, false, entityBinder, isEmbedded,
//					isIdentifierMapper, false, mappings,
//					inheritanceStatePerClass);
//			Component componentId = (Component) id;
//			componentId.setKey(true);
//			if (rootClass.getIdentifier() != null) {
//				throw new AnnotationException(
//						componentId.getComponentClassName()
//								+ " must not have @Id properties when used as an @EmbeddedId");
//			}
//			if (componentId.getPropertySpan() == 0) {
//				throw new AnnotationException(
//						componentId.getComponentClassName()
//								+ " has no persistent id property");
//			}
//			// tuplizers
//			XProperty property = inferredData.getProperty();
//			setupComponentTuplizer(property, componentId);
//		} else {
//			// TODO I think this branch is never used. Remove.
//
//			for (Ejb3Column column : columns) {
//				column.forceNotNull(); // this is an id
//			}
//			SimpleValueBinder value = new SimpleValueBinder();
//			value.setPropertyName(propertyName);
//			value.setReturnedClassName(inferredData.getTypeName());
//			value.setColumns(columns);
//			value.setPersistentClassName(persistentClassName);
//			value.setMappings(mappings);
//			value.setType(inferredData.getProperty(),
//					inferredData.getClassOrElement());
//			id = value.make();
//		}
//		rootClass.setIdentifier(id);
//		BinderHelper.makeIdGenerator(id, generatorType, generatorName,
//				mappings, localGenerators);
//		if (isEmbedded) {
//			rootClass
//					.setEmbeddedIdentifier(inferredData.getPropertyClass() == null);
//		} else {
//			PropertyBinder binder = new PropertyBinder();
//			binder.setName(propertyName);
//			binder.setValue(id);
//			binder.setAccessType(inferredData.getDefaultAccess());
//			binder.setProperty(inferredData.getProperty());
//			Property prop = binder.makeProperty();
//			rootClass.setIdentifierProperty(prop);
//			// if the id property is on a superclass, update the metamodel
//			final org.hibernate.mapping.MappedSuperclass superclass = BinderHelper
//					.getMappedSuperclassOrNull(
//							inferredData.getDeclaringClass(),
//							inheritanceStatePerClass, mappings);
//			if (superclass != null) {
//				superclass.setDeclaredIdentifierProperty(prop);
//			} else {
//				// we know the property is on the actual entity
//				rootClass.setDeclaredIdentifierProperty(prop);
//			}
//		}
//	}
//
//	private static PropertyData getUniqueIdPropertyFromBaseClass(
//			PropertyData inferredData, PropertyData baseInferredData,
//			AccessType propertyAccessor, Mappings mappings) {
//		List<PropertyData> baseClassElements = new ArrayList<PropertyData>();
//		XClass baseReturnedClassOrElement = baseInferredData
//				.getClassOrElement();
//		PropertyContainer propContainer = new PropertyContainer(
//				baseReturnedClassOrElement, inferredData.getPropertyClass());
//		addElementsOfClass(baseClassElements, propertyAccessor, propContainer,
//				mappings);
//		// Id properties are on top and there is only one
//		return baseClassElements.get(0);
//	}
//
//	private static void setupComponentTuplizer(XProperty property,
//			Component component) {
//		if (property == null) {
//			return;
//		}
//		if (property.isAnnotationPresent(Tuplizers.class)) {
//			for (Tuplizer tuplizer : property.getAnnotation(Tuplizers.class)
//					.value()) {
//				EntityMode mode = EntityMode.parse(tuplizer.entityMode());
//				component.addTuplizer(mode, tuplizer.impl().getName());
//			}
//		}
//		if (property.isAnnotationPresent(Tuplizer.class)) {
//			Tuplizer tuplizer = property.getAnnotation(Tuplizer.class);
//			EntityMode mode = EntityMode.parse(tuplizer.entityMode());
//			component.addTuplizer(mode, tuplizer.impl().getName());
//		}
//	}
//
//	private static void bindManyToOne(String cascadeStrategy,
//			Ejb3JoinColumn[] columns, boolean optional, boolean ignoreNotFound,
//			boolean cascadeOnDelete, XClass targetEntity,
//			PropertyHolder propertyHolder, PropertyData inferredData,
//			boolean unique, boolean isIdentifierMapper, boolean inSecondPass,
//			PropertyBinder propertyBinder, Mappings mappings) {
//		// All FK columns should be in the same table
//		org.hibernate.mapping.ManyToOne value = new org.hibernate.mapping.ManyToOne(
//				mappings, columns[0].getTable());
//		// This is a @OneToOne mapped to a physical o.h.mapping.ManyToOne
//		if (unique) {
//			value.markAsLogicalOneToOne();
//		}
//		value.setReferencedEntityName(ToOneBinder.getReferenceEntityName(
//				inferredData, targetEntity, mappings));
//		final XProperty property = inferredData.getProperty();
//		defineFetchingStrategy(value, property);
//		// value.setFetchMode( fetchMode );
//		value.setIgnoreNotFound(ignoreNotFound);
//		value.setCascadeDeleteEnabled(cascadeOnDelete);
//		// value.setLazy( fetchMode != FetchMode.JOIN );
//		if (!optional) {
//			for (Ejb3JoinColumn column : columns) {
//				column.setNullable(false);
//			}
//		}
//		if (property.isAnnotationPresent(MapsId.class)) {
//			// read only
//			for (Ejb3JoinColumn column : columns) {
//				column.setInsertable(false);
//				column.setUpdatable(false);
//			}
//		}
//
//		// Make sure that JPA1 key-many-to-one columns are read only tooj
//		boolean hasSpecjManyToOne = false;
//		if (mappings.isSpecjProprietarySyntaxEnabled()) {
//			String columnName = "";
//			for (XProperty prop : inferredData.getDeclaringClass()
//					.getDeclaredProperties(
//							javax.persistence.AccessType.FIELD.getType())) {
//				if (prop.isAnnotationPresent(Id.class)
//						&& prop.isAnnotationPresent(Column.class)) {
//					columnName = prop.getAnnotation(Column.class).name();
//				}
//
//				final JoinColumn joinColumn = property
//						.getAnnotation(JoinColumn.class);
//				if (property.isAnnotationPresent(ManyToOne.class)
//						&& joinColumn != null
//						&& !BinderHelper.isEmptyAnnotationValue(joinColumn
//								.name())
//						&& joinColumn.name().equals(columnName)
//						&& !property.isAnnotationPresent(MapsId.class)) {
//					hasSpecjManyToOne = true;
//					for (Ejb3JoinColumn column : columns) {
//						column.setInsertable(false);
//						column.setUpdatable(false);
//					}
//				}
//			}
//
//		}
//		value.setTypeName(inferredData.getClassOrElementName());
//		final String propertyName = inferredData.getPropertyName();
//		value.setTypeUsingReflection(propertyHolder.getClassName(),
//				propertyName);
//
//		ForeignKey fk = property.getAnnotation(ForeignKey.class);
//		String fkName = fk != null ? fk.name() : "";
//		if (!BinderHelper.isEmptyAnnotationValue(fkName)) {
//			value.setForeignKeyName(fkName);
//		}
//
//		String path = propertyHolder.getPath() + "." + propertyName;
//		FkSecondPass secondPass = new ToOneFkSecondPass(value, columns,
//				!optional && unique, // cannot have nullable and unique on
//										// certain DBs like Derby
//				propertyHolder.getEntityOwnerClassName(), path, mappings);
//		if (inSecondPass) {
//			secondPass.doSecondPass(mappings.getClasses());
//		} else {
//			mappings.addSecondPass(secondPass);
//		}
//		Ejb3Column.checkPropertyConsistency(columns,
//				propertyHolder.getEntityName() + propertyName);
//		// PropertyBinder binder = new PropertyBinder();
//		propertyBinder.setName(propertyName);
//		propertyBinder.setValue(value);
//		// binder.setCascade(cascadeStrategy);
//		if (isIdentifierMapper) {
//			propertyBinder.setInsertable(false);
//			propertyBinder.setUpdatable(false);
//		} else if (hasSpecjManyToOne) {
//			propertyBinder.setInsertable(false);
//			propertyBinder.setUpdatable(false);
//		} else {
//			propertyBinder.setInsertable(columns[0].isInsertable());
//			propertyBinder.setUpdatable(columns[0].isUpdatable());
//		}
//		propertyBinder.setColumns(columns);
//		propertyBinder.setAccessType(inferredData.getDefaultAccess());
//		propertyBinder.setCascade(cascadeStrategy);
//		propertyBinder.setProperty(property);
//		propertyBinder.setXToMany(true);
//		propertyBinder.makePropertyAndBind();
//	}
//
//	protected static void defineFetchingStrategy(ToOne toOne, XProperty property) {
//		LazyToOne lazy = property.getAnnotation(LazyToOne.class);
//		Fetch fetch = property.getAnnotation(Fetch.class);
//		ManyToOne manyToOne = property.getAnnotation(ManyToOne.class);
//		OneToOne oneToOne = property.getAnnotation(OneToOne.class);
//		FetchType fetchType;
//		if (manyToOne != null) {
//			fetchType = manyToOne.fetch();
//		} else if (oneToOne != null) {
//			fetchType = oneToOne.fetch();
//		} else {
//			throw new AssertionFailure(
//					"Define fetch strategy on a property not annotated with @OneToMany nor @OneToOne");
//		}
//		if (lazy != null) {
//			toOne.setLazy(!(lazy.value() == LazyToOneOption.FALSE));
//			toOne.setUnwrapProxy((lazy.value() == LazyToOneOption.NO_PROXY));
//		} else {
//			toOne.setLazy(fetchType == FetchType.LAZY);
//			toOne.setUnwrapProxy(false);
//		}
//		if (fetch != null) {
//			if (fetch.value() == org.hibernate.annotations.FetchMode.JOIN) {
//				toOne.setFetchMode(FetchMode.JOIN);
//				toOne.setLazy(false);
//				toOne.setUnwrapProxy(false);
//			} else if (fetch.value() == org.hibernate.annotations.FetchMode.SELECT) {
//				toOne.setFetchMode(FetchMode.SELECT);
//			} else if (fetch.value() == org.hibernate.annotations.FetchMode.SUBSELECT) {
//				throw new AnnotationException(
//						"Use of FetchMode.SUBSELECT not allowed on ToOne associations");
//			} else {
//				throw new AssertionFailure("Unknown FetchMode: "
//						+ fetch.value());
//			}
//		} else {
//			toOne.setFetchMode(getFetchMode(fetchType));
//		}
//	}
//
//	private static void bindOneToOne(String cascadeStrategy,
//			Ejb3JoinColumn[] joinColumns, boolean optional,
//			FetchMode fetchMode, boolean ignoreNotFound,
//			boolean cascadeOnDelete, XClass targetEntity,
//			PropertyHolder propertyHolder, PropertyData inferredData,
//			String mappedBy, boolean trueOneToOne, boolean isIdentifierMapper,
//			boolean inSecondPass, PropertyBinder propertyBinder,
//			Mappings mappings) {
//		// column.getTable() => persistentClass.getTable()
//		final String propertyName = inferredData.getPropertyName();
//		log.trace("Fetching {} with {}", propertyName, fetchMode);
//		boolean mapToPK = true;
//		if (!trueOneToOne) {
//			// try to find a hidden true one to one (FK == PK columns)
//			KeyValue identifier = propertyHolder.getIdentifier();
//			if (identifier == null) {
//				// this is a @OneToOne in a @EmbeddedId (the
//				// persistentClass.identifier is not set yet, it's being built)
//				// by definition the PK cannot refers to itself so it cannot map
//				// to itself
//				mapToPK = false;
//			} else {
//				Iterator idColumns = identifier.getColumnIterator();
//				List<String> idColumnNames = new ArrayList<String>();
//				org.hibernate.mapping.Column currentColumn;
//				if (identifier.getColumnSpan() != joinColumns.length) {
//					mapToPK = false;
//				} else {
//					while (idColumns.hasNext()) {
//						currentColumn = (org.hibernate.mapping.Column) idColumns
//								.next();
//						idColumnNames.add(currentColumn.getName());
//					}
//					for (Ejb3JoinColumn col : joinColumns) {
//						if (!idColumnNames.contains(col.getMappingColumn()
//								.getName())) {
//							mapToPK = false;
//							break;
//						}
//					}
//				}
//			}
//		}
//		if (trueOneToOne || mapToPK
//				|| !BinderHelper.isEmptyAnnotationValue(mappedBy)) {
//			// is a true one-to-one
//			// FIXME referencedColumnName ignored => ordering may fail.
//			OneToOneSecondPass secondPass = new OneToOneSecondPass(mappedBy,
//					propertyHolder.getEntityName(), propertyName,
//					propertyHolder, inferredData, targetEntity, ignoreNotFound,
//					cascadeOnDelete, optional, cascadeStrategy, joinColumns,
//					mappings);
//			if (inSecondPass) {
//				secondPass.doSecondPass(mappings.getClasses());
//			} else {
//				mappings.addSecondPass(secondPass,
//						BinderHelper.isEmptyAnnotationValue(mappedBy));
//			}
//		} else {
//			// has a FK on the table
//			bindManyToOne(cascadeStrategy, joinColumns, optional,
//					ignoreNotFound, cascadeOnDelete, targetEntity,
//					propertyHolder, inferredData, true, isIdentifierMapper,
//					inSecondPass, propertyBinder, mappings);
//		}
//	}
//
//	private static void bindAny(String cascadeStrategy,
//			Ejb3JoinColumn[] columns, boolean cascadeOnDelete,
//			Nullability nullability, PropertyHolder propertyHolder,
//			PropertyData inferredData, EntityBinder entityBinder,
//			boolean isIdentifierMapper, Mappings mappings) {
//		org.hibernate.annotations.Any anyAnn = inferredData.getProperty()
//				.getAnnotation(org.hibernate.annotations.Any.class);
//		if (anyAnn == null) {
//			throw new AssertionFailure("Missing @Any annotation: "
//					+ BinderHelper.getPath(propertyHolder, inferredData));
//		}
//		Any value = BinderHelper.buildAnyValue(anyAnn.metaDef(), columns,
//				anyAnn.metaColumn(), inferredData, cascadeOnDelete,
//				nullability, propertyHolder, entityBinder, anyAnn.optional(),
//				mappings);
//
//		PropertyBinder binder = new PropertyBinder();
//		binder.setName(inferredData.getPropertyName());
//		binder.setValue(value);
//
//		binder.setLazy(anyAnn.fetch() == FetchType.LAZY);
//		// binder.setCascade(cascadeStrategy);
//		if (isIdentifierMapper) {
//			binder.setInsertable(false);
//			binder.setUpdatable(false);
//		} else {
//			binder.setInsertable(columns[0].isInsertable());
//			binder.setUpdatable(columns[0].isUpdatable());
//		}
//		binder.setAccessType(inferredData.getDefaultAccess());
//		binder.setCascade(cascadeStrategy);
//		Property prop = binder.makeProperty();
//		// composite FK columns are in the same table so its OK
//		propertyHolder.addProperty(prop, columns,
//				inferredData.getDeclaringClass());
//	}
//
//	private static String generatorType(GenerationType generatorEnum,
//			Mappings mappings) {
//		boolean useNewGeneratorMappings = mappings.useNewGeneratorMappings();
//		switch (generatorEnum) {
//		case IDENTITY:
//			return "identity";
//		case AUTO:
//			return useNewGeneratorMappings ? org.hibernate.id.enhanced.SequenceStyleGenerator.class
//					.getName() : "native";
//		case TABLE:
//			return useNewGeneratorMappings ? org.hibernate.id.enhanced.TableGenerator.class
//					.getName() : MultipleHiLoPerTableGenerator.class.getName();
//		case SEQUENCE:
//			return useNewGeneratorMappings ? org.hibernate.id.enhanced.SequenceStyleGenerator.class
//					.getName() : "seqhilo";
//		}
//		throw new AssertionFailure("Unknown GeneratorType: " + generatorEnum);
//	}
//
//	private static EnumSet<CascadeType> convertToHibernateCascadeType(
//			javax.persistence.CascadeType[] ejbCascades) {
//		EnumSet<CascadeType> hibernateCascadeSet = EnumSet
//				.noneOf(CascadeType.class);
//		if (ejbCascades != null && ejbCascades.length > 0) {
//			for (javax.persistence.CascadeType cascade : ejbCascades) {
//				switch (cascade) {
//				case ALL:
//					hibernateCascadeSet.add(CascadeType.ALL);
//					break;
//				case PERSIST:
//					hibernateCascadeSet.add(CascadeType.PERSIST);
//					break;
//				case MERGE:
//					hibernateCascadeSet.add(CascadeType.MERGE);
//					break;
//				case REMOVE:
//					hibernateCascadeSet.add(CascadeType.REMOVE);
//					break;
//				case REFRESH:
//					hibernateCascadeSet.add(CascadeType.REFRESH);
//					break;
//				case DETACH:
//					hibernateCascadeSet.add(CascadeType.DETACH);
//					break;
//				}
//			}
//		}
//
//		return hibernateCascadeSet;
//	}
//
//	private static String getCascadeStrategy(
//			javax.persistence.CascadeType[] ejbCascades,
//			Cascade hibernateCascadeAnnotation, boolean orphanRemoval,
//			boolean forcePersist) {
//		EnumSet<CascadeType> hibernateCascadeSet = convertToHibernateCascadeType(ejbCascades);
//		CascadeType[] hibernateCascades = hibernateCascadeAnnotation == null ? null
//				: hibernateCascadeAnnotation.value();
//
//		if (hibernateCascades != null && hibernateCascades.length > 0) {
//			hibernateCascadeSet.addAll(Arrays.asList(hibernateCascades));
//		}
//
//		if (orphanRemoval) {
//			hibernateCascadeSet.add(CascadeType.DELETE_ORPHAN);
//			hibernateCascadeSet.add(CascadeType.REMOVE);
//		}
//		if (forcePersist) {
//			hibernateCascadeSet.add(CascadeType.PERSIST);
//		}
//
//		StringBuilder cascade = new StringBuilder();
//		for (CascadeType aHibernateCascadeSet : hibernateCascadeSet) {
//			switch (aHibernateCascadeSet) {
//			case ALL:
//				cascade.append(",").append("all");
//				break;
//			case SAVE_UPDATE:
//				cascade.append(",").append("save-update");
//				break;
//			case PERSIST:
//				cascade.append(",").append("persist");
//				break;
//			case MERGE:
//				cascade.append(",").append("merge");
//				break;
//			case LOCK:
//				cascade.append(",").append("lock");
//				break;
//			case REFRESH:
//				cascade.append(",").append("refresh");
//				break;
//			case REPLICATE:
//				cascade.append(",").append("replicate");
//				break;
//			case EVICT:
//			case DETACH:
//				cascade.append(",").append("evict");
//				break;
//			case DELETE:
//				cascade.append(",").append("delete");
//				break;
//			case DELETE_ORPHAN:
//				cascade.append(",").append("delete-orphan");
//				break;
//			case REMOVE:
//				cascade.append(",").append("delete");
//				break;
//			}
//		}
//		return cascade.length() > 0 ? cascade.substring(1) : "none";
//	}
//
//	public static FetchMode getFetchMode(FetchType fetch) {
//		if (fetch == FetchType.EAGER) {
//			return FetchMode.JOIN;
//		} else {
//			return FetchMode.SELECT;
//		}
//	}
//
//	private static HashMap<String, IdGenerator> buildLocalGenerators(
//			XAnnotatedElement annElt, Mappings mappings) {
//		HashMap<String, IdGenerator> generators = new HashMap<String, IdGenerator>();
//		TableGenerator tabGen = annElt.getAnnotation(TableGenerator.class);
//		SequenceGenerator seqGen = annElt
//				.getAnnotation(SequenceGenerator.class);
//		GenericGenerator genGen = annElt.getAnnotation(GenericGenerator.class);
//		if (tabGen != null) {
//			IdGenerator idGen = buildIdGenerator(tabGen, mappings);
//			generators.put(idGen.getName(), idGen);
//		}
//		if (seqGen != null) {
//			IdGenerator idGen = buildIdGenerator(seqGen, mappings);
//			generators.put(idGen.getName(), idGen);
//		}
//		if (genGen != null) {
//			IdGenerator idGen = buildIdGenerator(genGen, mappings);
//			generators.put(idGen.getName(), idGen);
//		}
//		return generators;
//	}
//
//	public static boolean isDefault(XClass clazz, Mappings mappings) {
//		return mappings.getReflectionManager().equals(clazz, void.class);
//	}
//
//	/**
//	 * For the mapped entities build some temporary data-structure containing
//	 * information about the inheritance status of a class.
//	 * 
//	 * @param orderedClasses
//	 *            Order list of all annotated entities and their mapped
//	 *            superclasses
//	 * 
//	 * @return A map of {@code InheritanceState}s keyed against their
//	 *         {@code XClass}.
//	 */
//	public static Map<XClass, InheritanceState> buildInheritanceStates(
//			List<XClass> orderedClasses, Mappings mappings) {
//		ReflectionManager reflectionManager = mappings.getReflectionManager();
//		Map<XClass, InheritanceState> inheritanceStatePerClass = new HashMap<XClass, InheritanceState>(
//				orderedClasses.size());
//		for (XClass clazz : orderedClasses) {
//			InheritanceState superclassState = InheritanceState
//					.getSuperclassInheritanceState(clazz,
//							inheritanceStatePerClass);
//			InheritanceState state = new InheritanceState(clazz,
//					inheritanceStatePerClass, mappings);
//			if (superclassState != null) {
//				// the classes are ordered thus preventing an NPE
//				// FIXME if an entity has subclasses annotated @MappedSperclass
//				// wo sub @Entity this is wrong
//				superclassState.setHasSiblings(true);
//				InheritanceState superEntityState = InheritanceState
//						.getInheritanceStateOfSuperEntity(clazz,
//								inheritanceStatePerClass);
//				state.setHasParents(superEntityState != null);
//				final boolean nonDefault = state.getType() != null
//						&& !InheritanceType.SINGLE_TABLE
//								.equals(state.getType());
//				if (superclassState.getType() != null) {
//					final boolean mixingStrategy = state.getType() != null
//							&& !state.getType().equals(
//									superclassState.getType());
//					if (nonDefault && mixingStrategy) {
//						log.warn(
//								"Mixing inheritance strategy in a entity hierarchy is not allowed, ignoring sub strategy in: {}",
//								clazz.getName());
//					}
//					state.setType(superclassState.getType());
//				}
//			}
//			inheritanceStatePerClass.put(clazz, state);
//		}
//		return inheritanceStatePerClass;
//	}
//
//	private static boolean hasAnnotationsOnIdClass(XClass idClass) {
//		// if(idClass.getAnnotation(Embeddable.class) != null)
//		// return true;
//
//		List<XProperty> properties = idClass
//				.getDeclaredProperties(XClass.ACCESS_FIELD);
//		for (XProperty property : properties) {
//			if (property.isAnnotationPresent(Column.class)
//					|| property.isAnnotationPresent(OneToMany.class)
//					|| property.isAnnotationPresent(ManyToOne.class)
//					|| property.isAnnotationPresent(Id.class)
//					|| property.isAnnotationPresent(GeneratedValue.class)
//					|| property.isAnnotationPresent(OneToOne.class)
//					|| property.isAnnotationPresent(ManyToMany.class)) {
//				return true;
//			}
//		}
//		List<XMethod> methods = idClass.getDeclaredMethods();
//		for (XMethod method : methods) {
//			if (method.isAnnotationPresent(Column.class)
//					|| method.isAnnotationPresent(OneToMany.class)
//					|| method.isAnnotationPresent(ManyToOne.class)
//					|| method.isAnnotationPresent(Id.class)
//					|| method.isAnnotationPresent(GeneratedValue.class)
//					|| method.isAnnotationPresent(OneToOne.class)
//					|| method.isAnnotationPresent(ManyToMany.class)) {
//				return true;
//			}
//		}
//		return false;
//	}
//
//}
